Hi I've got follow code:
angular.module("myApp", []).controller("myController", function($scope) {
$scope.currentOption;
$scope.setCurrentTimespan = function() {
//CODE HERE
};
$scope.timespanList = [{
id: 1,
name: 'morning',
startDate: '19.09.2016 06:00',
endDate: '19.09.2016 11:59'
}, {
id: 2,
name: 'noon',
startDate: '19.09.2016 12:00',
endDate: '19.09.2016 13:29'
}, {
id: 3,
name: 'afternoon',
startDate: '19.09.2016 13:30',
endDate: '19.09.2016 18:29'
}, {
id: 4,
name: 'evening',
startDate: '19.09.2016 18:30',
endDate: '19.09.2016 23:59'
}, {
id: 5,
name: 'night',
startDate: '20.09.2016 00:00',
endDate: '20.09.2016 05:59'
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<select ng-options="option as option.name for option in timespanList" ng-model="currentOption"></select>
</div>
I've got from the backend a object with items for my select. In this list there are some timespans like morning, noon, afternoon etc. This timespans have a startDate and an endDate, which also comes from the backend. For example, the timespan "morning" has follow startDate/endDate: [todays date] 06:00 / [todays date] 11:59. So what I want to do is, when I load the list and fill the select with ng-options, I would like to select the item from the list, which matches with the current timestamp. So I have to get the current date and time for example: 19.09.2016 09:45 and than search in the list the item which is defined for this timestamp and select it in the list. So I have to check the startDate/endDate with the current date / time. This should happen when the list was loaded.
So the result for my local time (19.09.2016 09:45) at this moment would be morning.
Has someone an idea how to do this? I didn't find any answers which can help me...Thanks
EDIT WITH SOLUTION:
I've found a perfect way to solve this problem: I found moment.js, which solves my requirements. After including it into my web app I start to use the queries and functions from moment.js to solve my problem. It works like this:
Get current timestamp (day, month, year, hour and minutes):
let currentTimestamp = moment(); //for example 19.09.2016 11:30
Than I loop throught my array with the timespans and parse the startDate/endDate with the moment.js to my required format DD.MM.YYYY HH:mm and then I can use the moment.js query isBetween() to check, if my currentTimestamp is between the startDate/endDate of each item like this:
this.timespanList.forEach(function(item) {
let startDate = moment(item.startDate, 'DD.MM.YYYY HH:mm'); // for example 19.09.2016 06:00
let endDate= moment(item.endDate, 'DD.MM.YYYY HH:mm'); // for example 19.09.2016 11:59
if(moment(currentTimestamp).isBetween(startDate, endDate)) {
$scope.currentOption = item;
}
});
So if the condition of the looped item is true, I can set the right option in my list. Here are some links of moment.js which describe, how to use it correcty - it's awesome!
moment.js docs: http://momentjs.com/docs/
moment.js parsing: http://momentjs.com/docs/#/parsing/
moment.js queries: http://momentjs.com/docs/#/query/
I hope this is usefull! An alternative solution from the answers which also would work is marked as correct. Thanks and cheers.
You can implement a custom filter to achieve this.
<select ng-options="option as option.name for option in timespanList | momentFilter" ng-model="currentOption"></select>
.filter('momentFilter',function(){
return function (object) {
var array = [];
angular.forEach(object, function (time) {
if(time.startDate.split(" ")[1] == '06:00' && time.endDate.split(" ")[1] == '11:59'){
array.push(time);
}
});
return array;
};
});
I have created a working plunker here.
Do little more work around to achieve this.
EDIT WITH SOLUTION FROM THE QUESTION:
I put my own solution which is in my edited question here so everyone can see it faster:
I've found a perfect way to solve this problem: I found moment.js, which solves my requirements. After including it into my web app I start to use the queries and functions from moment.js to solve my problem. It works like this:
Get current timestamp (day, month, year, hour and minutes):
let currentTimestamp = moment(); //for example 19.09.2016 11:30
Than I loop throught my array with the timespans and parse the startDate/endDate with the moment.js to my required format DD.MM.YYYY HH:mm and then I can use the moment.js query isBetween() to check, if my currentTimestamp is between the startDate/endDate of each item like this:
this.timespanList.forEach(function(item) {
let startDate = moment(item.startDate, 'DD.MM.YYYY HH:mm'); // for example 19.09.2016 06:00
let endDate= moment(item.endDate, 'DD.MM.YYYY HH:mm'); // for example 19.09.2016 11:59
if(moment(currentTimestamp).isBetween(startDate, endDate)) {
$scope.currentOption = item;
}
});
So if the condition of the looped item is true, I can set the right option in my list. Here are some links of moment.js which describe, how to use it correcty - it's awesome!
moment.js docs: http://momentjs.com/docs/
moment.js parsing: http://momentjs.com/docs/#/parsing/
moment.js queries: http://momentjs.com/docs/#/query/
I hope this is usefull! An alternative solution from the answers which also would work is marked as correct. Thanks and cheers.
Related
I want to test a calendar using cypress but it is not possible to select the date I need or any date, the ideal is a dynamic code, where I can enter number of days and it will select the correct number.
I am using this code and I am getting a error saying 'Cannot read property 'includes' of undefined'
let date = new Date()
date.setDate(date.getDate() + 5)
let futureDay = date.getDate()
console.log(futureDay)
let futureMonth = date.toLocaleString('default', { month: 'long' })
cy.get('.flatpickr-current-month')
.invoke('attr', 'flatpickr-monthDropdown-month')
.then(dateAttribute => {
if (!dateAttribute.includes(futureMonth)) {
cy.get('.flatpickr-next-month').click()
} else {
cy.get('.dayContainer')
.contains(futureDay)
.click()
}
})
I am able to add unique attributes in the elements if necessary (I tried and still it did not worked).
I was well tried a more simples code as:
cy.get('#inception_date').click()
cy.get('.flatpickr-days > .dayContainer',)
.contains('17')
.click({force: true})
cy.get('#inception_date')
.invoke('prop', 'value')
.should('contain', '2021-07-17')
and in this code I get an error of Timed out retrying after 4000ms: expected '2021-07-27' to include '2021-07-17' because it does not select the any date, it continues to be the date of today.
I am attaching 2 images if the DOM, maybe it can help to figure out what is the issue on my code.
Looking at the examples for flatPickrJS, you want
let date = new Date() // July 28
date.setDate(date.getDate() + 5) // Aug 2
let futureDay = date.getDate() // get 2 (integer)
let futureMonth = date.getMonth() // gets 6 (integer) for July
cy.get('.flatpickr-current-month select') // <select> is nested inside
.invoke('val') // this is the currently selected month
.then(dateAttribute => { // this is "6" for July (months are 0-based)
if (+dateAttribute !== futureMonth) { // +dateAttribute converts string to integer
cy.get('.flatpickr-next-month').click() // change month to Aug
}
cy.get('.dayContainer') // selects Aug 2
.contains(new RegExp(`^${futureDay}$`)) // which is July 28
.click() // plus 5 days
})
cy.get('input.flatpickr')
.invoke('val')
.should('eq', '2021-08-02') // passes
Summary of changes
get the numeric futureMonth not the string month name.
get the value of the current month from the <select> using .invoke('val').
compare current month to futureMonth, if not the same click next-month button.
take the day container click out of } else {, because you always need to select the day.
NOTE
Thanks to #SyedMuhammadAwais for finding a bug in the day selection code.
Using .contains(futureDay) does a partial match, but the calendar sometimes shows some days from the previous month, but they are disabled (not clickable).
So, if futureDay === 6 and the 26th of the previous month is showing, this disabled day will be selected and fail the test.
The solution is to use an exact text match, which can be done with a regex like this
.contains(new RegExp(`^${futureDay}$`))
This is the correct code with some amendments in code of #Steve Zodiac
date.setDate(date.getDate() + 8)
let futureDay = date.getDate()
let futureMonth = date.getMonth()
cy.log(futureDay) // get 6 (integer)
cy.log(futureMonth) // gets 7 (integer) for August
cy.get('input[placeholder="Day"]').click({force:true})
cy.wait(5000)
cy.get('.flatpickr-current-month > select > option').eq(0)
.invoke('val') // this is the currently
selected month
.then(dateAttribute => { // this is "6" for July
(months are 0-based)
if (+dateAttribute !== futureMonth) { // +dateAttribute converts string to integer
cy.get('.flatpickr-next-month').click({force: true}
}
cy.get('.dayContainer') // selects Aug 6
.contains(new RegExp(futureDay, "g"))
.click({force:true}) // plus 8 days
})
Here is my solution for the datepicker "previous days" exist or not issue when testing with Cypress.
Cypress.Commands.add(
'selectDate',
(picker, date) => {
let pickerDate = date.split('-')
let year = pickerDate[0]
let month = pickerDate[1]
let day = pickerDate[2]
cy.get(picker).click()
cy.get('.numInput.cur-year').eq(0).filter(':visible').clear().type(year)
let selectedMonth = parseInt(month, 10)
cy.get('.flatpickr-monthDropdown-months')
.eq(0)
.select(selectedMonth - 1)
//set day -> count how many 'prevMonthDay' is int the calendarMonth and add the number to the day we wants
//filtering here for get the correct day
// if there is any prev day !!
cy.get('.flatpickr-rContainer')
.then($body => {
if ($body.find('.flatpickr-day.prevMonthDay').length) {
return ['.flatpickr-day.prevMonthDay', ($body.find('.flatpickr-day.prevMonthDay').length).toString()];
}else{
return ['.flatpickr-day', '0'];
}
})
.then(selector => {
if(selector[0] === '.flatpickr-day.prevMonthDay'){
cy.log('prev days')
cy.get(`.dayContainer span:nth-child(${parseInt(day, 10) + parseInt(selector[1])})`)
.eq(0)
.click()
}else{
cy.log('no prev days')
cy.get(`.dayContainer span:nth-child(${parseInt(day, 10)})`)
.eq(0)
.click()
}
});
}
)
I have a CSV file with following format:
<pre id="csv" style="display:none">
DATES,WHOLESALE,ECOMMERCE,RETAIL,LOANS,BONDISSUER
01/10/2018 00:00,25,16,13,1,0
01/10/2018 01:00,24,5,9,3,2
01/10/2018 02:00,28,6,17,0,6
The data range is 01/10/2018 00:00 - 31/10/2018 00:00
Interval is every hour.
I am using highstock stacked column with 5 categories: WHOLESALE,ECOMMERCE,RETAIL,LOANS,BONDISSUER.
My problem is, that the highstock navigator displays the data incorrectly. I think I have to customise property in range selector or navigator, but I can't find any documentation online. I tried inputDateParser, but it didn't work. Here is the jsfiddle
inputDateParser: function (value) {
value = value.split(/[:\.]/);
return Date.UTC(
1970,
0,
1,
parseInt(value[0], 10),
parseInt(value[1], 10),
parseInt(value[2], 10),
parseInt(value[3], 10)
);
}
How do I get the data range to be correct: month of October 2018 according to the dates in CSV?
I should not see a whole year in the navigator, when I only have data for October.
Thanks much appreciated
You would need to format the dates correctly, it can be done using the beforeParse callback function, like this:
data: {
csv: document.getElementById('csv').innerHTML,
beforeParse: function(e) {
let csv = e.split('\n'); //split by newline
let processedTable = []
processedTable.push(csv[0].split(','))
for (let i = 1; i < csv.length; i++) {
let row = csv[i].split(',');
if (row.length != 6) //skip empty rows or rows with more/less columns
continue;
let date = row[0].split(' ')[0].split('/')
let time = row[0].split(' ')[1].split(':')
processedTable.push(
[(new Date(date[2], date[1] - 1, date[0], time[0], time[1], 0)).getTime(), //get the timestamp for the date
parseInt(row[1]),
parseInt(row[2]),
parseInt(row[3]),
parseInt(row[4]),
parseInt(row[5])
].join(',')
)
}
return processedTable.join('\n') //join the array into a string again
},
},
Every row is parsed, by splitting it apart, the date is found, and milliseconds since 1970 is returned by getTime(). Then we join the cells into strings, and lastly the rows into a long string. The reason we convert this back into a string, is because highcharts is going to read it in from a string.
Working JSFiddle example: https://jsfiddle.net/ewolden/spmtgv3a/
API on beforeParse: https://api.highcharts.com/highcharts/data.beforeParse
I'm trying to get my date range feature to be working correctly. Currently, when I try to select a date it is able to pick the date however when I click apply, it becomes an invalid date.
My code is the following:
AngularJS:
$scope.SimplePickerChange = function () {
$scope.date = {
startDate: $filter("date")(new Date(), 'yyyy-MM-dd'),
endDate: $filter("date")(new Date(), 'yyyy-MM-dd'),
};
};
HTML:
<input date-range-picker
id="date"
name="date"
class="form-control date-picker"
type="text"
ng-model="date"
ng-change="SimplePickerChange();"/>
Why are you changing model value by using filter? If you want to show start & end date in input field in yyyy-MM-dd format then just pass it to configuration options.
If you're using angular-daterangepicker then you can have code like below:
<input date-range-picker class="form-control date-picker" type="text" ng-model="date"
options="options" />
Where options is:
$scope.options = {
applyClass: 'btn-green',
locale: {
applyLabel: "Apply",
fromLabel: "From",
format: "YYYY-MM-DD", //will give you 2017-01-06
//format: "D-MMM-YY", //will give you 6-Jan-17
//format: "D-MMMM-YY", //will give you 6-January-17
toLabel: "To",
cancelLabel: 'Cancel',
customRangeLabel: 'Custom range'
}
}
So, just don't use ng-change function to update model value of the daterangepicker input field. If you really want to do that to post value to some web api then do it separately on some other variable, & not on model var of daterangepicker.
If you really want to set date variable value on load (initially) then start date & end date keep as date/moment objects & not the string (which date filter returns). So, it can be:
$scope.date = {
startDate: new Date(),
endDate: new Date()
};
Official Docs
Update: Plunker Example
Hi all I want to filtering the items like (Start and End Date) which is based on Due_date using the daterange functionality in meanjs app. then I tried many ways but unable to get the solution if any one knows the solution please help me..... My Plunk
Please look at my plunker to reference.
I Have displaying Due_date, so this is the field I want to use for filtering.
I have used some functionality to add invoice_Date and terms, which provides the answer like Due_date. for exmple:- invoice_date : 2016-09-10, terms : 6, the answer I got Due_date : 16-09-2016
so what I excatly looking for , I want to filter the Due_date as start date and end date : for example:- if we select start date like 16-09-2016 and end date is 25-09-2016 in table these two transaction only need to display or filter... so I have used daterange filter to achieve this solution, but unable to get the solution please help us.
the daterange filter is working perfectly if we using ng_module is invoice_date, but we don't know how to filter the Due_date filed please help us.... My Plunker
Controller:
.filter('dateRange', function() {
return function(records, dateKey, from, to) {
return records.filter(function(record) {
return !moment(record[dateKey], 'YYYY-MM-DD').isBefore(moment(from))
&& !moment(record[dateKey], 'YYYY-MM-DD').isAfter(moment(to));
});
}
})
Html:
<input type="date" class="form-control" name="from" ng-model="from">
<input type="date" class="form-control" name="to" ng-model="to">
Filter:-
ng-repeat="data in record | dateRange : 'invoice_date' : from : to"
This below the filed need to filter in table:-
Due_date:-
<td> {{addDays(data.invoice_date,data.terms) | date:'dd-MM-yyyy'}}</td>
I have created plunker for referrence:- My plunker
You can create a custom filter for this
HTML
<tr ng-repeat="data in record | myfilter:from:to">
<td> {{data.supplier_name}}</td>
<td> {{data.invoice_date}}</td>
<td> {{data.terms}}</td>
<td> {{addDays(data.invoice_date,data.terms) | date:'yyyy-MM-dd'}}</td>
</tr>
JS
app.filter("myfilter", function() {
return function(items, from, to) {
var df = from;
var dt =to;
var result = [];
for (var i=0; i<items.length; i++){
var date = new Date(items[i].invoice_date);
date.setDate(date.getDate() + parseInt(items[i].terms));
var tf = date;
if (tf > df && tf < dt) {
result.push(items[i]);
}
}
return result;
};
});
Using AngularJS I want to compare if date is greater than 3 days from today:
controller :
$scope.todayDate = new Date();
and dateHire from json object like dateHire":"2016-02-08T00:00:00"
html :
<tr ng-repeat ="emp in Employees">
<td>
<span class="label label-danger" ng-class="{'label-danger': (((todayDate | date:'d M') - (emp.dateHire | date: 'd M')) > 3)}"> {{emp.name}}</span>
</td>
</tr>
However, it does not work. what am I doing wrong.
Create a filter:
app.filter('unixDate',function(){
return function(date) {
return new Date(date).getTime();
}
});
then use it in your ng-class object:
ng-class="{'label-danger': (todayDate | unixDate) - (emp.dateHire | unixDate) > 86400000 * 3}"
You shouldn't add the JS logic to the view. You are trying to apply filters to your date: emp.dateHire | date: 'd M', which results in a string and then you try to subtract two strings. You end up doing something like '12 May' - '10 May' and the result of that is NaN.
You need to add a function to your controller or scope that accepts an employee object, then parses the employee.dateHire value into a Date object and finally returns the result of comparing that date with the current date.
Something like the following:
this.hireDateGreaterThanDays = function(emp, days) {
var now = new Date();
var dateHire = /* create a new date from the emp.dateHire attribute */
/**
* Compare date values here. Can use a library like MomentJS or
* plain JS Date objects as pointed out in other answers and comments.
*/
return (now - dateHire) > 3;
};