Mapping an array in Knockout - json

Here's what I have mocked out of my MVC code:
$(function(){
var ViewModel = function(){
this.items = ko.observableArray(null);
this.isLoading = ko.observable(true);
};
var data = [{"CreatedAt":"2013-12-29T22:00:20","Intro":"","Body":"","Title":"Test Item","Url":"/news-items/test-item/"},{"CreatedAt":"2013-12-29T21:13:34","Intro":"","Body":"","Title":"Test 1","Url":"/news-items/test-1/"},{"CreatedAt":"2013-12-29T16:03:56","Intro":"","Body":"<p>In the spirit of Christmas we are holding a Christmas photo competition for all members to enter. Prizes will be given to the best Christmas themed photo and the funniest photo. To enter, simply email your photo to: competition#bernese.org.nz. Your entry will be uploaded onto the club's Facebook page where all members can then vote by 'liking' their favourite photo.</p>\n<p>Entries close on the 20th of December and voting will be open until the 5th of January. The winning photo's will be displayed on the website.</p>","Title":"Christmas 2013 Photo Competition","Url":"/news-items/christmas-2013-photo-competition/"}];
var vm = new ViewModel();
ko.applyBindings(vm);
vm.items(test);
vm.isLoading(false);
})
I have mocked it from my MVC code, but the data object is basically what was returned from my controller. Knockout mapping is not working in this case and I suspect it's the way my data is returned. Is this a valid way, or do I need to wrap it in a DTO of sorts, e.g.: { items: [{item1:'...'},{item2:'...'}]}?
Thanks.
EDIT:
My mistake, I already defined items as observableArray. I use it this way so as soon as the page loads the loader gif is displayed. I have done it this way before, the only difference this time being the format of the json returned.
ADDED: Here's the example

I don't know if this is the only problem, but
this.items = ko.observable(null);
should be
this.items = ko.observableArray();
But I probably do the whole thing more like
$(function(){
var ViewModel = function(items){
this.items = ko.observableArray(items);
};
var data = [...];
var vm = new ViewModel(data);
})
UPDATE: Here is a fully working jsfiddle

The ko.mapping.fromJS(data) returns a ko.observableArray if the data parameter is already an array.
So you need to unwrap the returned ko.observableArray before assigning it:
var vm = new ViewModel();
ko.applyBindings(vm);
var test = ko.mapping.fromJS(data);
vm.items(test()); // you need to write `test()` to get the underlaying array.
Or you can directly fill in your already declared ko.observableArray with writing:
var vm = new ViewModel();
ko.applyBindings(vm);
ko.mapping.fromJS(data, {} /* mapping options */, vm.items);
Here is your updated JSFiddle.

Related

Create ko.observableArray from JSON object in Knockout JS

I have JSON object loaded to my view model. I want to push that into an observableArray.
function viewModel()
{
var self = this;
self.details = [{"id":1,"first_name":"fname1","last_name":"lname1","salary":1000.0},
{"id":2,"first_name":"fname2","last_name":"lname2","salary":2000.0},
{"id":3,"first_name":"fname3","last_name":"lname3","salary":3000.0}];
self.emp = ko.observableArray([new Model(self.details[0]),new Model(self.details[1]),new Model(self.details[2])]);
//This method works, but is very inefficient...
}
ko.applyBindings(new viewModel());
The solution I found was to feed each element individually, which is not practical.
I'm using JQuery. I found some solutions using knockout.mapping plugin. But I'm unable to add that plugin to my Eclipse workspace correctly.
I'm new to Knockout. Please help me find a solution to add the entire object to the observableArray.
I would probably use the mapping plugin personally, but this should also work
function viewModel()
{
var self = this;
self.details = [{"id":1,"first_name":"fname1","last_name":"lname1","salary":1000.0},
{"id":2,"first_name":"fname2","last_name":"lname2","salary":2000.0},
{"id":3,"first_name":"fname3","last_name":"lname3","salary":3000.0}];
var mapped = self.details.map(m => new Model(m));
//or
//var mapped = self.details.map(function(m) {return new Model(m);});
self.emp = ko.observableArray(mapped);
}
ko.applyBindings(new viewModel());

Populate FeatureCollection with values from bands of each individual image in an image collection in Google Earth Engine

In Google Earth Engine, I have loaded in a Featurecollection as a JSON which contains a few polygons. I would like to add columns to this FeatureCollection which gives me the mean values of two bands for each polygon and from each of the multiple images contained within the Image Collection.
Here is the code I have so far.
//Polygons
var polygons = ee.FeatureCollection('ft:1_z8-9NMZnJie34pXG6l-3StxlcwSKSTJFfVbrdBA');
Map.addLayer(polygons);
//Date of interest
var start = ee.Date('2008-01-01');
var finish = ee.Date('2010-12-31');
//IMPORT Landsat IMAGEs
var Landsat = ee.ImageCollection('LANDSAT/LT05/C01/T1') //Landsat images
.filterBounds(polygons)
.filterDate(start,finish)
.select('B4','B3');
//Add ImageCollection to Map
Map.addLayer(Landsat);
//Map the function over the collection and display the result
print(Landsat);
// Empty Collection to fill
var ft = ee.FeatureCollection(ee.List([]))
var fill = function(img, ini) {
// type cast
var inift = ee.FeatureCollection(ini)
// gets the values for the points in the current img
var mean = img.reduceRegions({
collection:polygons,
reducer: ee.Reducer.mean(),
});
// Print the first feature, to illustrate the result.
print(ee.Feature(mean.first()).select(img.bandNames()));
// writes the mean in each feature
var ft2 = polygons.map(function(f){return f.set("mean", mean)})
// merges the FeatureCollections
return inift.merge(ft2)
// gets the date of the img
var date = img.date().format()
// writes the date in each feature
var ft3 = polygons.map(function(f){return f.set("date", date)})
// merges the FeatureCollections
return inift.merge(ft3)
}
// Iterates over the ImageCollection
var newft = ee.FeatureCollection(Landsat.iterate(fill, ft))
// Export
Export.table.toDrive(newft,
"anyDescription",
"anyFolder",
"test")
In the console I get an error message
Element (Error)
Failed to decode JSON.
Error: Field 'value' of object '{"type":"ArgumentRef","value":null}' is missing or null.
Object: {"type":"ArgumentRef","value":null}.
In my csv file which is generated I get a new column called mean but this is populated with and no actual values.
There is no reason to use iterate() here. What you can do is a nested map(). Over polygons and then over images. You can flatten the resulting list of lists to turn it into a single list like this:
// compute mean band values by mapping over polygons and then over images
var results = polygons.map(function(f) {
return images.map(function(i) {
var mean = i.reduceRegion({
geometry: f.geometry(),
reducer: ee.Reducer.mean(),
});
return f.setMulti(mean).set({date: i.date()})
})
})
// flatten
results = results.flatten()
Script: https://code.earthengine.google.com/b65a731c78f78a6f9e08300dcf552dff
The same approach can be used with reduceRegions() as well, mapping over images and then over regions. However, you will have to map over the resulting features to set dates.
images.filterBounds(f) can be probably also added if your features cover a larger area.
PS: your table is not shared

Adding Fields to JSON in better way Javascript

I'm using Node-Red and the data is passed using JSON objects.
All of the data is in msg.payload. I want to add a new property, the TimeStamp, to the object without all of this unnecessary code...It works but I know this is sloppy.
Is there a better way?
var TimeStamp = new Date();
var newMsg = [ ];
newMsg.push({payload:
{ TimeStamp:TimeStamp ,
Humidity: msg.payload.Humidity,
Temperature: msg.payload.Temperature,
CO2: msg.payload.CO2,
Light: msg.payload.Light
}
});
return newMsg;
You can add the new property to the existing msg object and pass it on.
msg.payload.TimeStamp = new Date();
return msg;
This is the better approach as it leaves all other message properties untouched.

backbone.js fetch json success will not hit

i use fetch from backbone.js to load a json model but success will not hit.
var DialogModel = Backbone.Model.extend({
url : function() {
return '/messages/getDialog';
},
parse : function(res) {
return res.dialog;
}
});
var DialogView = Backbone.View.extend({
el: $("#page"),
initialize: function() {
var onDataHandler = function() {
this.render();
};
this.model = new DialogModel();
this.model.fetch({ success : onDataHandler});
},
render: function(){
var data = {
dialogModel : this.model
};
var form = new Backbone.Form({
model: data
});
$(this.el).html(form.render().el);
}
});
What happens now:
DialogView initialize is called.
this.model.fetch is called but the onDataHandler function will not be hit if success.
/messages/getDialog throws a json file back.
The json file is loading well as i can see in the network browser.
Thanks for your help!
Oleg
The problem you're having is due to a typical JS gotcha and not related to Backbone itself. Try
var that = this;
this.model.fetch({
success : function () {
that.render();
}
});
The way you're currently passing onDataHandler is problematic as it will cause this to refer to the global object instead of the DialogView, when the function is called.
This fiddle demonstrates the problematic version vs one that works.
(You may also want to take a look at JS strict mode which can shield you from this type of errors.)
Even better is to listen for an event:
this.model.on("sync", this.render).fetch();
I ran across this question while looking for something else, but the currently accepted answer drives me nuts. There's no good reason to be sprinkling this and that all over your code. Backbone (underscore) includes a context parameter that you can bind to.
that = this makes no sense. If you must implement obsolete 2007-era Crockford patterns, then say var self = this. Saying that = this is like saying left = right. Everyone Stop.

making a todolist in Mootools

i'm making a todolist in mootools and having the following problem. i'm store my todo items in a cookie but the issue is i can't read how many cookies i've set so i can get the value of them.
my question is: is there any way to count how many cookies i've so i can loop trough them and get the correct value.
when i put the getData in a console.log i'm getting my json but i also can't read the values from there. what am i doing wrong and wich other implementation do u advise me.
tnx in advance.
for now i've the following code.
window.addEvent('domready', function(){
$('add').addEvent('click', function(){
var value = $('todo').value;
var t = new Todo(value,"beschrijving",new Date(),1);
var storeData = JSON.encode(t);
var c = Cookie.write(value,storeData,{duration:1});
var getData = Cookie.read(value);
console.log(getData);
});
});
var Todo = new Class(
{
initialize: function(title,description,date,isDone){
this.title = title;
this.description = description;
this.date = new Date();
this.isDone = isDone;
},
getTitle:function()
{
return this.title;
},
getIsDone:function()
{
return this.isDone;
},
setIsDone:function(value)
{
this.isDone = value;
},
});
You seem to be missing the core point of cookies - when you set a cookie with a specified name, it overwrites the previous value of that cookie. With your current approach, it will never contain more than a single item.
You have to keep an array of todo items and serialize and store that array instead of the Todo object itself.
Also, you'll grow out of max cookie size quickly this way. I'd recommend using HTML5 LocalStorage instead. A base wrapper of LocalStorage can be found in Mootools Powertools.