KnockoutJS, mapping plugin, get notified when changes in model? - javascript

Im using knockoutJS in following way:
var messagesFromServer = getJSONData().messages; //this get msgs from server
ko.mapping.fromJS(messagesFromServer, {}, myobject.viewModel.Messages);
Then i am basically calling this every three seconds to update html table, and it works just fine, new rows are added if new data found from server. Now i would like to add custom callback when something has actually changed, for example when new messages are found.
How should i implement this?
thanks in adv,
-hk

You could convert the two objects into json, then compare them json strings.
var messagesFromServer = getJSONData().messages; //this get msgs from server
var newString = ko.toJSON(messagesFromServer);
var oldString = ko.toJSON(myobject.viewModel.Messages);
if(newString != oldString ) {
// something new
}
ko.mapping.fromJS(messagesFromServer, {}, myobject.viewModel.Messages);
See ko.toJSON doc
I hope it helps.

If the messages is array, you can use ko.utils.compareArrays to detect the changes and raise custom events yourself. Here is code example for comparing ko.observableArray(). Look for Comparing two arrays

Related

Javascript in HAML in Javascript

I've got a question that mightve been asked before but i have trouble finding a proper description. I hope someone can help me out.
In the code below on the line where i set var price i want to add the javascript variable accu_id to find a record in my DB through rails. How do I do this in embedded rails in javascript?
:javascript
$('#accu').change(function() {
var accu_id = $("#accu")[0].selectedOptions[0].value
var price = "#{currency(Product.find_by(id: accu_id).price2)}"
$('#price_accu').append(price)
});
Or is there an easier way to do this?
You have two options.
You can use AJAX request to get data from database
You can use mapping concept like following
var data = #processed_data // json data, which contains processed data in json format.
var accu_id = $("#accu")[0].selectedOptions[0].value
var price = data.accu_id;
Here the #processed_data contains data like following
#processed_data = currency_calculation
def currency_calculation
Product.all.map { |product| [product.id, currency(product.price2) ] }.as_json
end
Example
Assume products table have two entries then the #processed_data contain values like following
{ "1" => "20.00", "2" => "25.50" }
The above data directly assigned to js variable data and accessed like data.key
The first option is best choice and second is possible one.
Note : You can't use js variable inside ruby.

Why doesn't flot work with a array of (x,y) values? Javascript object versus arrays?

I'm creating a flot graph using some php-script. The php generates the data and uses json_encodeto pass this data to some javascript-flot code where I parse using jQuery.parseJson.
I was using the data-array filled with (x,y) values. Plotting this doesn't seem to work. If I encapsulate the array within an object flot is plotting it without problems. Why doesn't the first method work? I've added a jsFiddle below.
var data = '[["201518","1"],["201519","3"],["201520","6"]]',
data2 = '{"data":[["201518","1"],["201519","3"],["201520","6"]]}';
var set = jQuery.parseJSON(data),
set2 = jQuery.parseJSON(data2);
var placeholder = $('#placeholder');
$.plot(placeholder, [set2.data]);
//$.plot(placeholder, set); <= not working? Why?
jsfiddle
You need to pass an array:
$.plot(placeholder, [set])
// instead of `$.plot(placeholder, set)`
Two problems. First you need numbers and not strings when passing as an array (see here where it says
Note that to simplify the internal logic in Flot both the x and y
values must be numbers (even if specifying time series, see below for
how to do this). This is a common problem because you might retrieve
data from the database and serialize them directly to JSON without
noticing the wrong type. If you're getting mysterious errors, double
check that you're inputting numbers and not strings.
Second (as pointed out in another answer), you need the [array] around set. The following works:
$(document).ready(function () {
var data = '[[201518,1], [201519,3], [201520,6]]',
data2 = '{"data":[["201518","1"],["201519","3"],["201520","6"]]}';
var set = jQuery.parseJSON(data),
set2 = jQuery.parseJSON(data2);
var placeholder = $('#placeholder');
//$.plot(placeholder, [set2.data]);
$.plot(placeholder, [set]);
});

Knockout Mapping: JSON grows when mapping and saving multiple times

When I take a knockout object and serialize it to JSON by doing ko.toJSON, and then unserialize it from JSON using ko.mapping.fromJSON multiple times, the loaded object has this __ko_mapping__ property that recursively grows.
Sample code:
var joe = new Person();
for (var i = 0; i < 10; i++) {
var json = ko.toJSON(joe);
joe = ko.mapping.fromJSON(json);
}
Simple JSFiddle that reproduces it:
http://jsfiddle.net/Gc89Q/1/
How can I load and save multiple times without having the serialized json form grow to be gigantic?
I was considering just setting the __ko_mapping__ property to undefined when loading, but am wondering if there is a better way or something I am missing.
Is this a bug I file an issue for?
Don't overwrite the model. Instead, pass it to fromJSON so the model is updated:
ko.mapping.fromJSON(json, joe);
http://jsfiddle.net/Gc89Q/2/

jqPlot adding 0 value

I'm using the jqPlot library to build charts. I'm using some JS to fetch a JSON file, build a string using values from the JSON file, convert it to a nested array (the only format that jqPlot likes) and then passing to jqplot. jqPlot is reading the arry just fine and is plotting the correct values, but its adding a 0 value at the end.
Here's the string code:
$(function () {
$.getJSON("test.json", chartData);
function chartData(data) {
$.each(data.values, function(index,val){
chartValues += val + ",";
});
};
here's the code that converts it into a nested array:
var temp = new Array();
temp = chartValues.split(',');
var temp2 = new Array(temp);
alert(temp2);
So when temp2 is passed to jqplot it adds a zero, but when I pass it an identical nested array called test that is declared manually, it doesn't add the zero. Here they are for comparison:
var test = [[12,32,21,23,34,43,52,86,25,]];
and here's temp2
[[12,32,21,23,34,43,52,86,25,]]
Any ideas? I'd also appreciate any help with my logic in this, as I feel like I could be creating the nested array more elegantly.
I'm not sure 100% at this point but I think in .....86,25,]] is not right. That might be the reason to add a zero value. Try eliminating this. Another thing is that you can access the data arrays in json files directly using basic access methods. Try at json org.
Removing the last character in the string (before converting to an array) was the solution in this case.
newStr = chartValues.substring(0, chartValues.length-1);

Deduplicating using nodeJS

My goal is to take in a CSV file which contains approximately 4 million records and process each record while scrubbing the data of a particular field. The scrubbing process we have actually creates a reversible hash but is a time consuming process (almost 1 second). What I would like to do since there are only about 50,000 unique values for that field is to set them as properties of an object. Here is a pseudo example of how the object will be built. You can see that for duplicates I plan to just overwrite the existing value (this is to avoid having to loop through some if based search statement.
var csv = require('csv');
var http = require('http');
var CBNObj = new Object;
csv()
.fromPath(__dirname+'/report.csv',{
columns: true
})
.transform(function(data){
CBNObj[data['Field Value']] = data['Field Value'];
});
console.log(CBNObj);
This should create my object something like this.
myObj['fieldValue1'] = 'fieldValue1'
myObj['fieldValue2'] = 'fieldValue2'
myObj['fieldValue3'] = 'fieldValue3'
myObj['fieldValue1'] = 'fieldValue1'
myObj['fieldValue1'] = 'fieldValue1'
I have looked over some good posts on here about iterating over every property in an object (like this one Iterating over every property of an object in javascript using Prototype?) but I am still not exactly sure how to acccomplish what I am doing. How can I then take my object with 50k properties and essentially dump the values into an array so that I can end up with something like this?
myArray = ['fieldVaue1','fieldVaue2','fieldVaue3']
EDIT: I could also use some assistance on the first part here because I am getting a null value or undefined when I try and set the object properties. I also still need help then traversing through the object properties to build my array. Any help would be greatly appreciated.
You know that the keys of your object are the unique values you want. You just need an array. In node.js you can use Object.keys().
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
It's a standard way to take all the keys of an object (that aren't provided by the prototype chain) and put them into an array. So your example looks like this.
var csv = require('csv');
var AcctObj = new Object();
var uniqueArray;
csv()
.fromPath(__dirname+'/report.csv',{
columns: true
})
.on('data',function(data){
AcctObj[data['Some Field Value']] = data['Some Field Value'];
})
.on('end', function(){
uniqueArray = Object.keys(AcctObj);
});
Object.keys also does the hasOwnProperty check internally, so it's similar to the answer by #DvideBy0. It's just one step to the array you want.
var csv = require('csv');
var AcctObj = new Object();
csv()
.fromPath(__dirname+'/report.csv',{
columns: true
})
.on('data',function(data){
AcctObj[data['Some Field Value']] = data['Some Field Value'];
})
.on('end', function(){
for(var prop in AcctObj) {
if(AcctObj.hasOwnProperty(prop))
//Do something here....
}
});

Categories

Resources