
Great Responsibility Comes With Great Strength - AngularJS Safety

Undoubtedly, the angular gives you strength. But she needs to be used wisely. I tried to formulate three simple rules that I violated and suffered many times from this.
1. Make a copy of the object if it can undergo unwanted changes.
In the Angular, the default data is the same, and if you change it intentionally, accidentally or as a result of an error, all places of its use will be at risk. For example, we have a factory of empty entities that will be used to fill out forms.
module.factory("emptyEntity", function() {
var emptyObject = {
name:"",
surname:"",
address:{
city:""
street:"",
}
};
return {
createEmptyEntity: function(){
return emptyObject;
}
};
});
And further, in the form controller, we create this empty object in $ scope and use it as a form model.
$scope.model = mapper.createEmptyPetition();
What happens if this model changes when you enter the form, and then call mapper.createEmptyPetition () again for another form? Since the same instance of emptyObject is used everywhere, the changes will be reflected in it, and the next time you call mapper.createEmptyPetition (), we will get a dirty and used object. A great number of such moments can arise during development, and you need to be careful about distributing references to objects to the right and left. In this case, it should be done like this - to return a copy of the object so that its changes do not affect the original object:
createEmptyEntity: function(){
return angular.copy(emptyObject);
}
2. Do not lose the reference to the object / array if you do not want to lose data synchronization
A simple example.
We have a controller, in $ scope of which the array lies, and there is a function to clear the array:
module.controller("NewPetitionController", ["$scope", function($scope) {
$scope.myArray = [1,2,3,4];
$scope.cleanArray = function(){
$scope.myArray = [];
}
}
]);
And somewhere in the view you give the array to some directive, for example, which draws it.
What happens if you call the cleanArray function? The directive will calmly continue to display the good old full array, because it still has a link to it. And with the code "$ scope.myArray = []" we just created a new array and wrote a link to it in the myArray property, to which the my-array-viewer directive is absolutely parallel. To null an array without losing a reference to it, you just need to call $ scope.myArray.length = 0;
The same goes for objects. You can’t just take and assign a new object to a variable, you need to change the old one so that the rest of the application that has a link to this object does not lose it.
module.controller("NewPetitionController", ["$scope", function($scope) {
$scope.myObj = {foo: "bar"};
$scope.setObj = function(newObj){
//$scope.myObj = newObj; //Так делать нельзя, это приведёт к утере ссылки
angular.extend($scope.myObj, newObj); //нужно вот так, чтобы изменился исходный объект
}
}
]);
3. Be careful with $ scope children
Many directives such as ng-if, ng-include create a child of $ scope. What does it mean? These directives will create a new instance of $ scope, in the prototype property of which there will be a parent scope - standard javascript inheritance. It follows that changing simple properties (string, number, boolean etc.) in a child scope will NOT affect the parent scope, since simple properties are copied during inheritance. In contrast to them, objects in prototype inheritance are passed by links, so changing the properties of objects will be displayed in the parent scope.
Therefore, this should not be done, this will not work:
Второй блок отображается!
Instead, you need to have a special object in $ scope for such things, let's call it viewModel
app.controller("MainCtrl", function($scope) {
$scope.viewModel = {};
});
Второй блок отображается!
Write in the comments about what other features of the angular-way you happened to fill in cones.