AngularJS - Change the $scope object - javascript

I have a very weird issue.
I have an object under the $scope
I using an angular.foreach loop but there is a problem.
when I'm trying to set a value depending on langKey(where langKey is 'en' or 'el') all the values are being updated by ingoring the langKey.
$scope.finalObject[langKey]['servicesElements'][itemKey]['name'] = something;
the problem still exists when I simply use the console in order to change the values from there.
I'm setting the value 'myCustomText' to the el version of the object
$scope.finalObject.el['servicesElements'][itemKey]['name'] = 'myCustomText'
BUT if i run this one
$scope.finalObject.en['servicesElements'][itemKey]['name']
it returns 'myCustomText' with no reason because what I changed was the el version not the en.
Is this normal? I'm totally stuck
Thank you in advance

Well guys,
The problem was that I had declared the two different objects with the same source.
$scope.finalObject.el.servicesElements = something;
and
$scope.finalObject.en.servicesElements = something
I didn't have seen that before, but the browser was behaving like I have typed
$scope.finalObject.en.servicesElements = $scope.finalObject.el.servicesElements = something
and in every change of the one the other was following.
(in php is called pointer)
The solution was to use the angular's copy function
http://docs.angularjs.org/api/angular.copy
So I simply used this SO answer Reset a model with angular.js did this
$scope.tmpVar = something;
$scope.finalObject.en.servicesElements = angular.copy($scope.tmpVar);
$scope.finalObject.el.servicesElements = angular.copy($scope.tmpVar);

Related

RxJS 5 Observable and variable scope aka Why is my variable unreadable

Angular 2 RC4 app written in TypeScript 1.9 and RxJS 5 beta 6
I'm having a really hard time understanding why my class variable is not passed to the Observable generating function when I subscribe. My code is below but you can see it running at this Plunker (see app/app.component.ts
//this is the problematic var. Can't pass its updated value to the Observable
input = 'nothing'; //<- default value
ngOnInit(){//<- this runs right after class constructor
//set to the value we want to send to the server
this.input = 'something';
}
start(){
//to make sure input = something when we subscribe
this.print("Subscribing when input = "+this.input);
this.source.subscribe(d=>this.print(d));
}
//Simulate sending input to the server
source = this.queryServer(this.input)
.do(()=>this.print('Emitting new value...'));
//server just returns what it received
queryServer(input){return Observable.from(['Server sees '+input])}
print(value){this.log.push(value);}
log=[];
output when I start the subscription by calling start()
Subscribing when input = something
Emitting new value...
Server sees nothing
How come even though the class property is something when we call subscribe, nothing is passed to queryserver()? I tried making input an object such as input={d:'something'} thinking that maybe the problem had to do with passing values instead of references but the result was the same.
It's happening because you are passing the default value of input to queryServer when you construct the component. Even though you change it in ngInit it has already been used to construct the pipeline that you then subscribe to. You are essentially doing the following:
this.input = "nothing";
const copyOfInput = this.input;
this.input = "something";
console.log(copyOfInput); //-> nothing
You have changed what this.input is pointing at but copy of it you made still points to the old value. I would posit that you actually want to initialize the pipeline in ngInit and not as part of the construction of the object.
Thanks to #paulpdaniels for the helpful input. He suggested that I compose the source in ngOnInit, after I have set input=something. That works for the first value of input but in practice input will continue to change after ngOnInit is complete, so the source will once again emit obsolete data.
What still really surprises me is that even when the input is an object (rather than a simple string), the problem in the OP persists. Since objects are assigned by reference in JS, I expected differently.
The code design I opted for is to compose source inside a setter for input. That way, each time that value is set, source is refreshed:
source:Observable<any>;
_input = 'nothing';
get input(){return this._input;}
set input(val){
this._input = val;
source = this.queryServer(val)
.do(()=>this.print('Emitting new value...'));
}
Still feels hack-y to me but I'm brand new to Observables so maybe there is no better way. If there is, I hope someone will teach it to me.

Angular JS: how to "load" an individual record from a json dataset?

I have json data, an array of 50 objects representing people. Each one has parameters like id and lastName.
I load this into my controller via a resolve, EmployeeResolve, and into a variable _this.employees
I also load via $state params from a previous page a rowNumber variable that holds the ID of the record the user clicked on: _this.rowNum = $stateParams.id;let's say the id is 5.
I would like to assign to a variable now the object number 5 (for want of a better way of explaining) so that in my HTML I can bind to it as in {{controller.lastName}}
What's the syntax for getting the 5th item out of employees?
UPDATE
After several helpful comments and answers, I've gotten this far (people are now packages):
_this.recordNum = Number($stateParams.id);
_this.packages = PackagesResolve;
_this.currentPackage = _this.packages.filter(function(pkg) {
return pkg.id === _this.recordNum;
});
$log.debug('package from filter', _this.currentPackage[0].status);
Note though, I expected after all this for _this.currentPackage to contain an object, so I could simply bind to its props in the html as in currentPackage.last_name But it does not. It's a resource and I need to use the above _this.currentPackage[0].status in the log statement to get anything. And that's not going to allow binding.
A colleague suggested modifying my resolve as such
PackagesResolve: function($log, MockDataFactory) {
return MockDataFactory.query({filename: 'packages'}).$promise.then(function(response) {
return response;
});
}
Adding the whole $promise.then part. No real difference.
To reiterate what I am trying to do:
PackagesResolve is getting a json array of 50 objects. I want to be able to get the CURRENT object when its row in a table of that json is clicked.
And no, #jdvp it's not a duplicate of that other post at all. I need to do this with Angular, not jquery or straight js.
If I'm understanding your issue correctly: the object returned by resolve is the resolved promise. The "data" of the resolved promise, which in this case would be the expected array of people info, is stored inside resolve.data. So for e.g. you have EmployeeResolve, you can reference the array and store it using:
Editing based on comments:
// Assuming you've done all error checking...
_this.employees = EmployeeResolve.data;
// Now _this.employees has the array of people info.
$scope.controller = {};
$scope.controller.variableName = _this.employees[$stateParams.id];
// Now, you can access your object in your template using controller.variableName.
Now although I wouldn't recommend writing code like that in your final version, I'm sure you get the gist. ;)
Additional notes: The reason I'm creating an empty object and storing it as controller on the scope is because your question stated it. I am assuming you have your own reasons for wanting to namespace your variable inside of controller.
Hope this helps!

strange angularJs variable behavior

Kindly explain me this behavior. I have decalred 2 variables.
$scope.data = {'value' : 123};
$scope.v1 = $scope.data;
Now if i change the value
$scope.data.value = 2;
and try to print
alert('old value is '+$scope.v1.value);
It gives me output as 2 whereas I think it should give me value as 123.
Kindly tell me that is it the same behavior like Java where one variable has different instances and change in one reflects in another ?
As you're guessing you are not creating a new object when you assign $scope.data to $scope.v1. You're just "pointing" $scope.v1 to $scope.data which implies that any change that you do to $scope.data will be reflected also in $scope.v1.
If you want to have different elements you should make a copy of the object. Look at angular.copy
Yes. You want to use angular.copy() to solve your current issue.
Anyways this all happens because of making one Object equal to another is assigning a reference; not creating a copy.

JavaScript: how to pass object value from one function to another

I am using code lines like the following in order to fetch data from an intranet website:
util.setProp(obj, "firstNameOld", $(msg).find('#fname_a').text());
Now I have another function in the same file where I want to use the above again, resp. the value of that object - currently I am hard-coding this ('Test') for test purposes:
util.setProp(obj, "firstNameNew", 'Test');
How can I pass the value from the firstNameOld object in one function to the firstNameNew object in another function ? If a solution with global variables is better here than this would work as well.
Many thanks for any help with this, Tim.
I've never used the framework that includes util But I imagine that if there is a setProp() then there has to be a getProp() or something similar.
If so, you could do something like
util.setProp(obj, "firstNameNew", util.getProp(obj, "firstNameOld"));
This also relies on the assumption that you want to copy from two properties in the same object.
If not, then pass the desired source object in the getProp() call.
My guess is that functions (or properties) are called "firstNameOld" and "firstNameNew", so the first time you get it from selector, second time you want to do the same.
Try to use the local variable like that:
var text = $(msg).find('#fname_a').text();
//
util.setProp(obj, "firstNameOld", text);
//
util.setProp(obj, "firstNameNew", text);

How do I set an object property within a Backbone model

Right, so I have a number of Backbone models going on, and in one of them I have an object that has a set of keys and values, of which the values are modified by locating the key from a string.
So I started out with code that was built on the below principle, I am quite comfortable with how and why this code will output true:
var boundData = {
text: 'value'
}
var key = 'text';
return (boundData[key] === 'value');
So to set the value of the property, I would do something like:
boundData[key] = 'new value';
Then I decided to translate all of my existing classes to Backbone models. And the problem that I hit, was that I can no longer change my properties with an equals operator, instead I use the set method provided by Backbone for models. This method takes a string as the first parameter, this string identifies the key for the variable that I am trying to change.
this.set("boundData[" + settings.name + "]", new OpenCore.boundData(settings));
This does not seem to work, and neither does this:
this.set("boundData." + settings.name, new OpenCore.boundData(settings));
SOLVED IT. Whilst I was writing out the question, I figured out a way to do it. But thought I would leave it here in case others run into the same problem.
This is a solution, whilst it may not be the best (I'd be interested if someone could get the original way sorted.), but it seems to work.
var boundData = this.get('boundData'); //Create a reference of the object with get().
boundData[settings.name] = new OpenCore.boundData(settings); //Update this reference.
//The change will be reflected in the original instance or you can just:
this.set('boundData', boundData);
Hope this helps someone else out!
This is a solution, whilst it may not be the best (I'd be interested if someone could get the original way sorted.), but it seems to work.
var boundData = this.get('boundData'); //Create a reference of the object with get().
boundData[settings.name] = new OpenCore.boundData(settings); //Update this reference.
//The change will be reflected in the original instance or you can just:
this.set('boundData', boundData);
Hope this helps someone else out!

Categories