I want to make performance optimization of my app. And I came across the following issue. Let me have an object with multiple keys (which are not changeable within one object) and a view similar to this:
<div ng-if="vm.model">
<span>{{ vm.model.property1 }}</span>
<span>{{ vm.model.property2 }}</span>
<span>{{ vm.model.property3 }}</span>
</div>
I would have wanted to use one-time bindings for my properties, but if I change vm.model inside the controller to another object by reference, then my expressions won't be updated inside the view, unless I do an explicit change of model to a falsy value and trigger a digest cycle somehow, to force the whole block to be removed and then recompiled.
Is there a way I can avoid having these 3 redundant watchers, since these properties shouldn't be watched, but only the parent object reference should.
https://docs.angularjs.org/guide/expression
Try this
<div ng-if="vm.model">
<span>{{ ::vm.model.property1 }}</span>
<span>{{ ::vm.model.property2 }}</span>
<span>{{ ::vm.model.property3 }}</span>
</div>
#Alexey Katayev Based on my understanding of your problem the issue is not related with AngularJS but its a point about how JavaScript works with the references passed to functions.
Check this post on Is JavaScript a pass-by-reference or pass-by-value language? and the below simple example, I hope it will be of help to you in order to solve your problem.
angular
.module('demo', [])
.controller('DefaultController', DefaultController);
function DefaultController() {
var vm = this;
vm.model = data[0];
vm.changeModel = changeModel;
function changeModel(model) {
model.property1 = data[1].property1;
model.property2 = data[1].property2;
model.property3 = data[1].property3;
}
}
var data = [
{ property1: 'Property 1', property2: 'Property 2', property3: 'Property 3' },
{ property1: 'Property 4', property2: 'Property 5', property3: 'Property 6' },
{ property1: 'Property 7', property2: 'Property 8', property3: 'Property 9' }
];
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController as vm">
<button type="button" ng-click="vm.changeModel(vm.model)">Change Model</button>
<div ng-if="vm.model">
<span>{{ vm.model.property1 }}</span>
<span>{{ vm.model.property2 }}</span>
<span>{{ vm.model.property3 }}</span>
</div>
</div>
</div>
Related
I have an array and I want to take specific element from it using directive (for example array[0]), but I don't understand how to achieve it. I realize that this is the basics of angularjs but I can't find anywhere a solution. Please help :)
Here's the array
$scope.array = [
{
text: '1',
},
{
text: '2',
},
{
text: '3',
}]
And I use that construction in a view
<div ng-repeat="element in array">
<content></content>
</div>
And this is what contains that directive
<p>{{array.text}}</p>
In html :
In content directive you will have to add
bindToController: {data: "="}
You could set the same var in your directive instead of data
<div ng-repeat="element in array">
<content></content>
</div>
directive:
<p>{{element.text}}</p>
If the directive is about customer data you should use {{ customer.text }}, if that is the case you can continue using the same scope like this ...
<div ng-repeat="customer in array">
<content></content>
</div>
directive:
<p>{{customer.text}}</p>
Is my firts time working with ionic and angular. I have a checkbox list populate from controller, when I click on check the view show my change but if I want view this change on controller show me the old value. I need add/substract the values
html
<div class="item-text-wrap">
<ion-list>
<ion-checkbox ng-repeat="item in listTypeProduct"
ng-model="item.checked"
ng-checked="item.checked"
ng-change="add(listTypeProduct)" >{{ item.text }}
</ion-checkbox>
</ion-list>
</div>
<div class="item">
<pre ng-bind="listTypeProduct | json"></pre>
</div>
the print on page is working!
This is my controller
app.controller('CotCtrl', function($scope, $ionicSideMenuDelegate,$rootScope) {
$scope.listTypeProduct = [
{ text: "a1", checked: false , value:4500 },
{ text: "a2", checked: false , value:2000 },
{ text: "a3", checked: false , value:1200 }
];
$scope.add = function(list){
console.log(JSON.stringify(list));
};
But on my controller when I iterate the array give me the old information.
Method "add" I want iterate the list with update values for example
angular.forEach(list, function(val, key) {
if( checked && (value) )
$scope.total += total+val.value;
});
To add all checked values.
Quoting AngularJS documentation here
Note that this directive "ngChecked" should not be used together with ngModel, as this can lead to unexpected behaviour.
This said, use only ng-model to bind your checkbox to the model in the controller.
Controller code:
$scope.items = [];
$scope.items = [{'name': 'name x', 'id': 'xyz'},
{'name': 'name y', 'id': 'uqh'}];
console.log(document.getElementById('xyz')+'<--- Element is created');
View
<div ng-repeat="item in items">
<div id="{{item.id}}"/>
</div>
So here, as soon as I have created the divs dynamically, i want to draw a chart in each of the div. But I can't get access to it.
The console shows null. I understand whats going wrong here. But can someone suggest me the right way to go about in such a scenario.
The alternative that I know is to bind function calls like this, but then it would get called multiple times. So i cant go ahead in that manner either.
<div ng-repeat="item in items">
<div ng-bind="drawInElement(item.id)" id="{{item.id}}"/>
</div>
well, I would simply suggest to create a directive like this :
<div ng-repeat="item in items">
<div draw-my-chart="{{item.id}}"/>
</div>
Then in your js :
angular.directive('drawMyChart', function() {
return {
link: function(scope, element, attrs) {
// access your element here ...
}
};
})
I am trying to get the accordions to toggle correctly through the directive ng-click. If I have Item one open how do I get it to expand all the accordions? Item two and Item three will continue to expand and collapse but Item one stays stagnant.
Plunker
alternately you can adjust your buttons so that they just loop through the children.
html:
<div ng-controller="AccordionDemo">
<div >
<div class="stuff_in_the_middle" >
<div ng-repeat="m in results" ng-click="m.open = !m.open" style="margin-bottom:20px">
<div heading="{{m.label}}" is-open="m.open" style="background-color:#d2d2d2; cursor:pointer" >
{{m.label}}
</div>
<div ng-show="m.open" style="padding:10px">
contents
</div>
</div>
<span class="btn btn-default" ng-click="toggle(false)">Collapse All</span>
<span class="btn btn-default" ng-click="toggle(true)">Expand All</span>
</div>
<hr />
</div>
</div>
JS:
var module = angular.module('plunker', []);
module.controller('AccordionDemo', ['$scope',
function ($scope) {
$scope.results = [
{label: 'Item 1', open: false},
{label: 'Item 2', open: false},
{label: 'Item 3', open: false}
];
$scope.toggle = function(state) {
$scope.results.forEach(function(e) {
e.open = state;
});
}
}
]);
see it working here: http://plnkr.co/edit/T6iv7mSoat9SQBwSIFJP
You have a problem with scopes. Simple rule is to never set variable value from ng-click or similar directives if you gonna use this variable outside - in parent.
It is caused by ng-repeat, which creates scope and if you will try to define new variable within it(you are doing it, because you have used name plunker, instead of opened), it will be defined only to current item in repeat.
You can use setter function to set it to right scope. So, here we go: http://plnkr.co/edit/h3MtKywiOaIQhpnAzWLT?p=preview
I need to call a js function when an ng-repeat template is created:
<div ng-repeat="item in items">
<input id="ip{{item.id}}">
<script>$(function () { $('#ip{{item.id}}').kendoDatePicker(); });</script>
</div>
The id is replaced as expected, but angular doesn't seem to work inside script tags.
That is correct, Angular will not evaluate expressions in script tags. You will need to use a directive that will initialize the Kendo plugin for each element.
The good news is Kendo already has a module for integrating with Angular, so you might as well just use that. Here is a plunk I put together showing it in a repeater.
<div ng-repeat="item in items">
<label for="{{item.id}}">{{item.id}}</label>
<div>
<input kendo-date-picker ng-model="item.value" />
</div>
</div>
Controller:
angular.module("demo", ['kendo.directives'])
.controller('DemoCtrl', ['$scope',
function($scope) {
$scope.items = [{
id: 'item1',
value: null
}, {
id: 'item2',
value: null
}, {
id: 'item3',
value: null
}, {
id: 'item4',
value: null
}];
}
]);