Ember issue with setting attribute value - javascript

I have an Ember Route class defined as below;
export default Ember.Route.extend({
model: function() {
var compObj = {};
compObj.gridPara = this.get('gridPara');
return compObj;
},
gridPara: function() {
var self = this;
var returnObj = {};
returnObj.url = '/myService';
// setting some other returnObj attributes
var summaryObj = {
total: {
label: "Total 1",
value: "100"
},
additional: [{
label: 'Label 2',
value: 'val2'
}, {
label: 'Label 3',
value: 'val3'
}]
};
returnObj.summary = summaryObj;
return returnObj;
},
actions: {
dataLoaded: function(resp) {
// Here I get the service response and want to set (or overwrite) the summaryObj values
this.get('gridParams').summary.total.value = resp.numRows;
}
}
});
My template looks like
{{my-grid params=this.gridPara dataLoaded="dataLoaded"}}
Now I want to set the "summary" on returnObj
I have verified that I get "resp" inside dataLoaded callback.
But I get the following error when trying to do
this.get('gridParams').summary.total.value = resp.numRows;
Uncaught Error: Assertion Failed: You must use Ember.set() to set the value property (of [object Object]) to 100.
Also how do I set/push for "additional" array inside summaryObj

As the error states, you must use set to the the value (Im assuming you have gridParams defined somewhere?):
this.set('gridParams.summary.total.value', resp.numRows);
In order to push a new object, try this:
var additional = this.get('gridParams.additional');
additional.push({label: ..., value: ....});
this.set('gridParams.additional', additional);

not 100% sure, but give it a try:
Watch out the property names. I suppose it's a wording error to declare 'gridPara' and trying to get 'gridParams'
You should retrieve the value like this
this.get('gridParams.summary.total.value')
What you are trying with the last sentence is a setting, but like it was plain JS. In Ember you should do it this.set('gridParams.summary.total.value',resp.numRows)

Just adding to #Remi answers ,the best practice would be to use
Ember.set('gridParams.summary.total.value', resp.numRows);
To answer the question in your comment
Say you want to update additional array at index i.Just do
var updateItem = additional[i];
Ember.set(updateItem.propertyname,newValue)
//Here propertyname would be the property you want to update and new Value is the new value which you want to set to that property

Related

make the query dynamically to change using sanity.io groq

Hi there I'm trying to make a post request where I want to update one field on sanity.io
this is my query
patch: {
id: "f6c46b53-9313-4354-a4d6-7a40b06ee4c0",
set: {
`rewardItem[_key == \"${key}\"].lastTimeReward`: "TEst",
},
}
but this won't let me even run my project,
its giving me this error on console.log: Unexpected token;
When I do my query like this, it works
patch: {
id: "f6c46b53-9313-4354-a4d6-7a40b06ee4c0",
set: {
"rewardItem[_key == \"e88959e43ce7\"].lastTimeReward": "Test",
},
}
}]
Thanks a lot.
Your set-property is an object, and you can't enter a dynamic key directly into the object. To do what you are trying to do here, you can wrap the dynamic key in square brackets like this. That should give you the output you desire
const variable = "example"
const a = { [`template ${variable}`]: "value" }
console.log(a)

Return value of static method of nested model is ignored in parent model (expressjs)

I have a model in expressjs that has a property which is an instance of another model, basically a nested model, like this:
// nested.js
var NestedPropDef = {
someProp: { type: String, default: '' },
};
var schema = new Schema(NestedPropDef, { minimize: false });
schema.statics = {
getInstance() {
var nestedObject = new NestedProp();
nestedObject.someProp = 'something';
console.log('[first log] value of nestedObject:', nestedObject);
return nestedObject;
},
});
var NestedProp = mongoose.model('NestedProp', schema);
exports.NestedPropDef = NestedPropDef;
exports.NestedProp = NestedProp;
// parent-file.js
var NestedPropDef = require('./nested').NestedPropDef;
var NestedProp = require('./nested').NestedProp;
var schema = new Schema({
otherProp: { type: String, default: '' },
nestedProp: NestedPropDef,
});
schema.methods.updateNestedProp = function (data, callback) {
this.nestedProp = NestedProp.getInstance();
console.log('[second log] value of nestedProp:', this.nestedProp);
this.otherProp: data.otherProp;
console.log('[third log] value of this:', this);
this.save(callback);
});
var Parent = mongoose.model('Parent', schema);
module.exports = Parent;
Each of those console.log statements yield the following:
[first log] value of nestedObject: {
someProp: 'something'
}
So I know the instance of the nested property is being created correctly.
[second log] value of nestedProp: {}
I don't understand why this is an empty object. For some reason, the value returned by .getInstance is not saved to this.nestedProp.
[third log] value of this: {
otherProp: 'some value'
}
I don't understand why nestedProp is completely missing from this object.
So basically I can't figure out why the return value from the static method of the nested object is not getting used by the parent model. Any ideas will be very welcome, thanks!
Update: it appears that the bug is linked to using this JWT library, though I don't know why. I don't use the library in any routes/code related to this problem. I think they're linked because the bug goes away when I revert to the commit before I installed the JWT library.
Update 2: the JWT lib was actually unrelated to the issue, but the problem was introduced with a recent change to mongoose. As of mongoose#5.9.24, the log statements would be as follows (and this is what I want):
[first log] value of nestedObject: {
someProp: 'something'
}
[second log] value of nestedProp: {
someProp: 'something'
}
[third log] value of this: {
otherProp: 'some value',
nestedProp: {
someProp: 'something'
}
}
I know that I can export the schema of NestedProp instead of its definition, and that would mostly fix the issue, but it adds the _id field to nestedProp and that wasn't happening before. In other words, doing this:
// nested.js
...
exports.NestedPropSchema = schema;
exports.NestedProp = NestedProp;
// parent-file.js
var NestedPropSchema = require('./nested').NestedPropSchema;
var NestedProp = require('./nested').NestedProp;
var schema = new Schema({
otherProp: { type: String, default: '' },
nestedProp: NestedPropSchema,
});
...
causes this:
[third log] value of this: {
otherProp: 'some value',
nestedProp: {
someProp: 'something',
_id: ...
}
}
I know there's a way to disable the automatic addition of the _id, but my objective is to restore the previous functionality so that other subtle bugs don't creep up on me. How can I restore the results I was seeing in 5.9.24? Or was I always nesting incorrectly (and Mongoose was just working with my incorrect nesting)?

Angular won't apply object changes to it's properties

I have an object like this:
$scope.user = {key: 'j16er48', name: 'Foo', title: 'Bar'}
And the template is:
<div ng-if="user.key">{{user.name}}</div>
Now, if I change the value of key property to null or false directly, then the div won't be displayed. But If I change the whole object to this:
$scope.user = {key: false, name: 'Foo', title: 'Bar'}
Nothing happens. Angular seems to still watch the old object and the old value of key property.
I also tried to use $scope.$apply() after assigning a new object to user but still no chance.
Am I missing something?
== UPDATE ==
After so much tests I found a very strange behavior in Angular scope. The issue happens due to an unwanted assignment by reference (or a two-way binding maybe).
I have an object called defaultUser which is : {key: false, name: 'Foo', title: 'Bar'}. Assuming this:
var defaultUser = {key: false, name: null, title: null};
$scope.user = defaultUser;
// here I change a property of $scope.user
$scope.user.key = 'j16er48';
$scope.resetUser = function(){
// Now defaultUser.key equals 'j16er48'
alert(defaultUser.key);
// That's why this line does nothing
$scope.user = defaultUser;
}
So when I tried to assign defaultUser to user object again, I thought is has been reset, whereas defaultUser has been changed and is equal to user. right now.
Is that normal? Does Angular assume all assignments by reference? Is that a two-way binding? Have I been crazy or what else?
https://jsfiddle.net/amraei/g1b5xomz/3/
It seems that you are using an old version of Angular.
I've created two Fiddles, the first is using Angular 1.1.1 (https://jsfiddle.net/dcg74epp/) and the second using Angular 1.2.1 (https://jsfiddle.net/6vy4jn6q/).
They both have a very minimal controller and don't follow any style guidelines, but should get your point across.
app.controller('TestController', function ($scope) {
$scope.user = {key: 'j16er48', name: 'Foo', title: 'Bar'};
var secondUser = {key: false, name: 'Foo', title: 'Bar'};
var tmp;
$scope.changeUser = function () {
tmp = $scope.user;
$scope.user = secondUser;
secondUser = tmp;
};
});
So, if using a newer version of Angular is possible for you, use it.

ko.mapping observableArray always trigger subscription

I am working with ko.mapping plugin in order to map data coming from an ajax request.
Setting the key i expect that subscription is not triggered in this case but it's always raised; i can't understand why. Thx in advance.
var arraySource = [{ Prop: 1, Prop2: 1 }, { Prop: 2, Prop2: 2 }];
var mappedArray = ko.observableArray([]);
mappedArray.subscribe(function (data) {
console.log(data);
});
window.setInterval(function () {
ko.mapping.fromJS(arraySource, {
key: function (data) {
return data.Prop;
}
}, mappedArray);
}, 3000);
Demo: http://jsfiddle.net/xvzAj/
Based on the comment in the docs it sounds like passing the third parameter to .fromJS will overwrite the properties of the array which would trigger the notification.
ko.mapping.fromJS(data, {}, someObject); // overwrites properties on
someObject
Source: http://knockoutjs.com/documentation/plugins-mapping.html
In the knockout.mapping.js ln 627, the array contents are replaced which is triggering the subscription notification.
mappedRootObject(newContents);
https://github.com/SteveSanderson/knockout.mapping/blob/master/build/output/knockout.mapping-latest.debug.js
As #Andrew Walters suggested the subscription will always be triggered, because the entire array is overwritten with the new content.
I found a way to recognoze what really changed by reading the knockout release 3 : http://blog.stevensanderson.com/2013/10/08/knockout-3-0-release-candidate-available/
var myArray = ko.observableArray(["Alpha", "Beta", "Gamma"]);
myArray.subscribe(function(changes) {
// For this example, we'll just print out the change info
console.log(changes);
}, null, "arrayChange");
inside the subscription it's possible to get the added, deleted and retained elements in a very simple way !

prototype JSON to Object

The following is part of a JSON string returned from the server:
{
col1: {
caption: 'Workspace',
combodata: {
c_0: {
id: 0,
value: 'Filter...'
},
c_1: {
id: 1,
value: 'Tax'
},
c_2: {
id: 2,
value: 'HR'
}
}
}
}
After eval, I can access .caption, and .combodata is visible in Firebug as an object, with c_0 and c_1 visible as objects inside .combodata, with id and value in both c_0 and c_1.
How do I step through each object in .combodata? I tried .combodata.each(c), but that throws an exception. I won't know the names of the objects in .combodata during run time.
You can use a regular for loop for that:
for(var key in obj.col1.combodata) {
var combo_obj = obj.col1.combodata[key];
...
}
Can I suggest that you do not eval() the JSON that's returned? What you should be doing is:
var jsondata = { ... };
var obj = JSON.parse(jsondata);
The reason is because eval'ing a string can be dangerous. Imagine if your JSON data looked like this:
"{ some json data here }; alert(document.cookie)"
When you eval that, the users cookie is displayed to them. Now think what happens if instead of alert, that cookie is posted to an attackers URL. They now have access to that users account if such exists.
if
var result = {col1: { caption: 'Workspace',combodata: {c_0: {id: 0,value: 'Filter...'},c_1: {id: 1, value: 'Tax'},c_2: {id: 2, value: 'HR'}}}};
then
for ( i in result.col1.combodata ) {
var item = result.col1.combodata[i];
//Do stuff with item
}
I have found the following to work as well and will use this:
Object.values(col1.combodata).each(function(c2) {
id = c2.id;
});

Categories

Resources