JavaScript (Angular) ForEach Loop Changes Not Applying - javascript

I have an array of objects with a date formatted in MMMM Do YYYY format. I need to convert this into a UNIX timestamp to arrange them and then convert them back into the readable date format.
However, in doing this. It seems that my changes from within the forEach callback are not applied to the $scope.lalala variable.
My code:
function compare(a, b) {
if (a.date < b.date)
return -1;
if (a.date > b.date)
return 1;
return 0;
}
$scope.lalala = arrayofincompleteorders;
$scope.lalala.forEach(function(hiVanilla, index) {
hiVanilla.date = moment(hiVanilla.date, 'MMMM Do YYYY').format('x');
if (index == $scope.lalala.length - 1) {
$scope.lalala.sort(compare); timestamps as expected
console.log($scope.lalala); //logs the date property with unix
callback();
}
});
console.log($scope.lalala); //logs the date property with unix timestamps, why?
function callback() {
$scope.lalala.forEach(function(order, index) {
console.log(order.date); //unix timestamp
$scope.lalala[index].date = moment(order.date, 'x').format('MMMM Do YYYY');
console.log($scope.lalala[index].date); //formatted timestamp
});
};
Edit: I have the same problem even with the angular.forEach loop in the callback:
function callback(){
angular.forEach($scope.lalala, function(value, key) {
console.log(value.date);
value.date = moment(value.date, 'x').format('MMMM Do YYYY');
console.log($scope.lalala[key].date);
});
console.log("fire!");
$scope.apply();
};
I get the dates to change successfully but then it says that $scope.apply() is not a function which borks the rest of my script.
Edit2:
I got rid of the callback and have everything in one angular.forEach but it still doesn't apply?
$scope.lalala = arrayofincompleteorders;
angular.forEach($scope.lalala, function(hiVanilla, key) {
hiVanilla.date = moment(hiVanilla.date, 'MMMM Do YYYY').format('x');
if (key == $scope.lalala.length - 1) {
$scope.lalala.sort(compare); //timestamps as expected
console.log($scope.lalala); //logs the date property with unix
console.log(hiVanilla.date); //unix timestamp
hiVanilla.date = moment(hiVanilla.date, 'x').format('MMMM Do YYYY');
console.log($scope.lalala[key].date); //formatted timestamp
}
});
console.log($scope.lalala); //logs the date property with unix timestamps, why?

It looks like I was using angular.forEach in a way that it was not designed.
The following worked, basically I just assigned it by pushing it into an empty array rather than trying to alter the array from which I was looping inside of:
$scope.lalala=[];
var log = = arrayofincompleteorders;
angular.forEach(log, function(value, key) {
if(value.complete!="TRUE")
{
i++;
value.date = moment(value.date, 'x').format('MMMM Do YYYY');
this.push(value); //put the new value in $scope.lalala as specified below
}
}, $scope.lalala);

Related

I have a function that I want to use to separate data into lists using this boolean function

function date_is_in_the_future(dateAdd){
// turn '2018-01-01' from a string to an object
input_date_object = new Date(dateAdd);
// Get todays date as an object
today_date = new Date();
// if the inpute_date_object is bigger than today_date, it will return false
boolean_result = input_date_object > today_date;
// return result
return boolean_result;
}
What do I have to do to this function in order to use it in my JavaScript?
Just call it;
console.log(date_is_in_the_future('2019-01-01'));
console.log(date_is_in_the_future('2017-01-01'));
function date_is_in_the_future(dateAdd){
//turn '2018-01-01' from a string to an object
input_date_object = new Date(dateAdd)
//Get todays date as an object
today_date = new Date()
//if the inpute_date_object is bigger than today_date, it will return false
boolean_result = input_date_object > today_date
//return result
return boolean_result
}

When emitting a date in a CouchDB Map function - what is being called on the date object?

I'm experimenting with emitting Date objects as the key in a map function, and can't understand what is happening when the Date object isn't parsed correctly.
Using a simple example record set :
{
"_id": "e3681a4f5ce5685b777659804e9fd9f1",
"date": "2016-04-04T16:02:09.058+01:00" // okay datestring
}
{
"_id": "99a5c50967a279e1d7fef1a4ed18d7fb",
"date": "2016-04-34T16:02:09.058+01:00" // invalid datestring
}
{
"_id": "43a435ce71a4b92ab0dd4fe9d91fbbb2",
"date": "text" // invalid datestring
}
And the following map function :
function(doc) {
var date = new Date(doc.date);
emit(date,1);
}
Gives the following result set :
{"total_rows":3,"offset":0,"rows":[
{"id":"43a435ce71a4b92ab0dd4fe9d91fbbb2","key":null,"value":1},
{"id":"99a5c50967a279e1d7fef1a4ed18d7fb","key":null,"value":1},
{"id":"e3681a4f5ce5685b777659804e9fd9f1","key":"2016-04-04T15:02:09.058Z","value":1}
]}
Where are the null values for the key coming from? It's not calling toString() or toISOString() on the dates as they would return "Invalid Date"
What's going on here?
Essentially, it works like this:
function emit(key, value) {
var row = { id: currentDocId(), key: key, value: value };
appendToOutput(JSON.stringify(row));
}
So it should be easy to see where the values come from, given that toJSON() on an invalid date returns null.
In reality it's not the emit() function that does this at all, but the default rendering implementation used when no list function is supplied.
while (row = getRow()) {
send(JSON.stringify(row))
}

Hide past date from JSON via jquery

I have a JSON file with information in it, there's title, date, etc, etc,
Format in the JSON:
date:"01/01/2001"
My current code to arrange by date
$(element).find('.ct-googleMap--search').val('');
arrayMarker = [];
dataMarkers = data;
dataMarkers.sort(function (a, b) {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
Now I want to add hiding dates that have passed. I've tried some options, but now I'm here.
Have you looked at the filter function?
var now = new Date();
//filter out old values first, so the sort is working with a smaller result
dataMarkers = data.filter(function(d) {
return d > now;
});
dataMarkers.sort(function (a, b) {
//equal values don't require the date object construction
if (a.date === b.date) {
return 0;
}
return new Date(a.date) > new Date(b.date); //based on borisdiakur's comment
});

add items into two arrays (future and past dates) based on date

I am trying to find a way to sort posts into two arrays: upcoming and current (upcoming posts are in the future and current have already been posted).
All posts have a scheduledPubDate that is a date string in the format YYYY-MM-DDT00:00:00. and todays date has to be a Date object as it will need to stay relevent (I am using moment())
Is it possible to compare these two different things without having to use a .split and compare the month / day /year separately
angular.forEach(data.items, function (key, index) {
if (moment(key.scheduledPubDate) > moment()) {
$scope.upcomingPosts.push(item[index]);
} else if (moment(key.scheduledPubDate) <= moment()) {
$scope.currentPosts.push(item[index]);
};
});
Presumably you want the string treated as UTC, a simple parser for that is:
// Expected format YYYY-MM-DDT00:00:00
function parseUTC(s) {
var b = s.split(/\D/);
return new Date(Date.UTC(b[0], b[1]-1, b[2], b[3], b[4], b[5]));
}
Note that this doesn't allow for invalid dates. If needed, an extra line if code is required. So now you can do:
if (parseUTC(key.scheduledPubDate) > new Date()) // or Date.now()
You really don't need moment.js for this.
JavaScript's built-in Date object will help you here.
var date = Date.parse('2014-01-21T12:45:13');
date < Date.now() // true
For the purpose of an example, let's assume items is an array of posts:
var items = [{
scheduledPubDate: '2014-01-21T12:45:13'
// ...other keys here
}, {
scheduledPubDate: '2017-03-01T15:21:00'
} // ...and so on
];
Then a reduce operation over items can categorize the posts:
var posts = items.reduce(function (memo, item) {
memo[Date.parse(item.scheduledPubDate) <= Date.now() ? 'current' : 'upcoming'].push(item);
return memo;
}, { current: [], upcoming: [] });
Now posts.current will contain an array of all posts from items whose scheduledPubDate is before the current date, and posts.upcoming will contain an array of all scheduled posts.
Edited to use Date.parse, to avoid unreliable behavior pointed out by RobG. This requires that all dates be in the YYYY-MM-DDT00:00:00 format you specified; if that is not the case, another solution will be required.
You have to specify the date format of the string
var format = "YYYY-MM-DDT00:00:00";
angular.forEach(data.items, function (key, index) {
if (moment(key.scheduledPubDate, format) > moment()) {
$scope.upcomingPosts.push(item[index]);
} else if (moment(key.scheduledPubDate, format) <= moment()) {
$scope.currentPosts.push(item[index]);
};
});
Working example (See the console.log): http://jsbin.com/fejaxiguce/1/edit?html,output
First create an array of elements, in any order, and then use the .sort() method.
http://www.w3schools.com/jsref/jsref_sort.asp
var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a-b});
Just substitute the above logic with your own. a and b above can be objects.

registerEntityTypeCtor initializers does not seem to trigger when using property path expand

I want all Date types in my entities to always be converted to momentjs. The solution (Code 2) I used for this works fine for getResources (Code 1), the initializer is triggered for both the 'Event and 'Shift' entities. But when I call getUser the expand works as it should and I get the right data for both 'Order' and 'Event', but the initializer for 'Event' never triggers. Any ideas why? Is it because I'm using a property path expand?
Also, if you can think of a better solution to convert all Date types in my entities to momentjs I will gladly accept that too.
Code 1:
var getResources = function () {
var query = breeze.EntityQuery
.from("Resources")
.expand("Event, Shift")
.orderBy("ResourceId");
return manager.executeQuery(query)
.fail(fail);
}
var getUser = function () {
var query = breeze.EntityQuery
.from("LoggedInUser")
.expand("Order.Event")
.orderBy("Email");
return manager.executeQuery(query)
.fail(fail);
}
Code 2:
function configureMetadataStore(metadataStore) {
metadataStore.registerEntityTypeCtor('Shift', null, momentInitializer);
metadataStore.registerEntityTypeCtor('Event', null, momentInitializer);
metadataStore.registerEntityTypeCtor('Order', null, momentInitializer);
}
function momentInitializer(entity) {
var newMoment,
prop;
for (prop in entity) {
if (ko.isObservable(entity[prop])) {
if (entity[prop]() instanceof Date) {
newMoment = ko.observable(moment(entity[prop]()));
entity[prop] = newMoment;
}
}
}
}
I am sure there is a better and more detailed answer for this, but from what I understand you are probably trying to display the date in a given format, not actually convert it in the database, correct?
If you are using a binding handler such as Knockout.js you can just change the format in which it is displayed instead of converting the date/time stamp. I am always cautious of converting the dates just to display them because I have had issue in the past with the database getting mad at me for such a thing.
Here is an example of a custom binding handler to show date time as May 29th, 2013, 2:22:00 pm
ko.bindingHandlers.DateTime = {
update: function (element, valueAccessor) {
var value = valueAccessor();
var date = moment(value());
var strDate = date.format('MMMM Do YYYY, h:mm:ss a');
$(element).text(strDate);
}
};

Categories