Why array in $scope doesn't updated using array concat method? - arrays

When I use concat method, my $scope is not updated
var anotherList = ["2", "3", "4"];
$scope.list = [];
$scope.list.concat(anotherList);
But using array push method in a loop, my $scope gets updated

Your syntax is wrong. You need to assign the return value of .concat() to your scoped array.
$scope.list = $scope.list.concat(anotherList);
Alternatively, if you used call() you could bind the result directly to the scoped array without the need to "reassign" since it would be done under the hood for you.
$scope.list.concat.call(anotherList);
See the documentation.

What David said is correct. Just to add: concat() doesn't modify the array, it just return a new array based on the parameters received. Check this for more info:
http://www.w3schools.com/jsref/jsref_concat_string.asp

If you want to maintain the original array, instead of concat you can do:
Array.prototype.push.apply($scope.list, anotherList);

Related

Get dynamic scope array variable value in angularjs

I have a scope array variable which i am trying to access dynamically. Its value has been already set.
Its like this.
$scope.setp = { arr: [] };
$scope.setp.arr[0] = "sample Value";
When I am trying to access it dynamically as below I get undefined.
console.log($scope['setp.arr[0]']);
However I am able to access it directly using the following.
console.log($scope.setp.arr[0]);
The way of dynamically getting value of scope variable works fine for others but fails when the variable name contains square brackets i.e. [ ].
I followed this example but no success for scope variable containing array or square brackets [ ].
Also dynamically setting of scope array variable using $parse service works fine as in below.
var scopeVariable = $parse('setp.arr[0]');
scopeVariable.assign($scope, "new Value");
This won't work console.log($scope['setp.arr[0]']); as its trying to access a property setp.arr[0]. You can access it like console.log($scope['setp']['arr'][0]);

How to pass a simple array data in ngStorage,$localstorage?

So lets say I want to define an var array=['a','b','c']
How do I pass this array into localStorage ?
Should I just simply write $localStorage.data = array;?
And also how to check if that array $localStorage.data is not empty and not undefined?
You can simply store in localstorage as:
localStorage.setItem("data", JSON.stringify(array));
and later retrieve it as
$scope.data= JSON.parse(localStorage.getItem("data"));
You can check $scope.data by doing
console.log($scope.data);
How do I pass this array into localStorage ?
Should I just simply write $localStorage.data = array;?
Yes, you simply put it like this:
$localStorage.data = array
And also how to check if that array $localStorage.data is not empty and not undefined?
Check it like simple variable
if($localStorage.data){
console.log('empty');
} else{
console.log('Data', $localStorage.data);
}
ngStorage
Right from AngularJS homepage: "Unlike other frameworks, there is no need to [...] wrap the model in accessors methods. Just plain old JavaScript here." Now you can enjoy the same benefit while achieving data persistence with Web Storage.

Is AngularJS Filter dys'Functional'?

I'm new to Angular, and was curious why the difference in syntax:
$log.info("Hi");
So info is a function of $log and take a parameter string.
but...
$filter('uppercase')('Hi');
Why does "Hi" outside the function?
Why not $filter('uppercase','HI')
Whats happening here?
In this case $filter is a factory method. $filter('uppercase') creates the uppercase filter, which in turn is a method. Without assigning the created method to a variable you are calling the method in place.
It's more or less a shortcut for writing
var uppercaseFilter = $filter('uppercase');
var filteredString = uppercaseFilter(originalString);

AngularJS assigning scope variable from scope

In angularJS, when trying to assign a scope variable from the value of another scope variable, the value of the derived variable is empty. In the example, I'd like to have a scope reference for the car, and also for a specific car part (which may change later in the application).
Example:
$scope.car = Car.get(); //async http service that returns a JSON car object
$scope.selectedCarPart = $scope.car.brakes;
HTML:
<div>{{car.engine}} - {{selectedCarPart}}</div>
Output:
v8 -
Why is selectedCarPart empty?
I assume that you get call is async, so when you assign the selectedCarPart, your $scope.car is currently null and doesn't have yet some brakes.
You have to wait the end of your get call and assign the value of the resulting JSON car object in the success callback of your http service.
Accepted answer from Apercu is correct. You can also use more general solution which is using $watch. In that case you write this:
$scope.$watch('car',function(newValue) {
$scope.selectedCarPart = newValue['brakes'];
}, true);
More information about $watch can be found here: https://docs.angularjs.org/api/ng/type/$rootScope.Scope
Even if that would work, I think there's a better way.
<div>{{car.engine}} - {{car[selectedPartKey]}}</div>
That way, you can just change the value of selectedPartKey to 'brakes'. Your way, if car's values change, it won't be reflected...

$watch not being triggered on array change

I'm trying to figure out why my $watch isn't being triggered. This is a snippet from the relevant controller:
$scope.$watch('tasks', function (newValue, oldValue) {
//do some stuff
//only enters here once
//newValue and oldValue are equal at that point
});
$scope.tasks = tasksService.tasks();
$scope.addTask = function (taskCreationString) {
tasksService.addTask(taskCreationString);//modifies tasks array
};
On my view, tasks is clearly being updated correctly as I have its length bound like so:
<span>There are {{tasks.length}} total tasks</span>
What am I missing?
Try $watch('tasks.length', ...) or $watch('tasks', function(...) { ... }, true).
By default, $watch does not check for object equality, but just for reference. So, $watch('tasks', ...) will always simply return the same array reference, which isn't changing.
Update: Angular v1.1.4 adds a $watchCollection() method to handle this case:
Shallow watches the properties of an object and fires whenever any of the properties change (for arrays this implies watching the array items, for object maps this implies watching the properties). If a change is detected the listener callback is fired.
Very good answer by #Mark. In addition to his answer, there is one important functionality of $watch function you should be aware of.
With the $watch function declaration as follows:
$watch(watch_expression, listener, objectEquality)
The $watch listener function is called only when the value from the current watch expression (in your case it is 'tasks') and the previous call to watch expression are not equal. Angular saves the value of the object for later comparison. Because of that, watching complex options will have disadvantageous memory and performance implications. Basically the simpler watch expression value the better.
I would recommend trying
$scope.$watch('tasks | json', ...)
That will catch all changes to the tasks array, as it compares the serialized array as a string.
For one dimensional arrays you may use $watchCollection
$scope.names = ['igor', 'matias', 'misko', 'james'];
$scope.dataCount = 4;
$scope.$watchCollection('names', function(newNames, oldNames) {
$scope.dataCount = newNames.length;
});

Resources