angularjs: forEach in ng-click - angularjs

I have a problem with implementing "select All" feature for simple list:
Controller:
$scope.numbers = [{v:1},{v:2},{v:3},{v:4}];
Template:
select All
<p ng-repeat='n in numbers'>
<label>
<input type="checkbox" ng-model="n.selected">
Label: {{ n.v }}
</label>
</p>
It seems angular parser cannot process the ng-click statement:
Error: [$parse:syntax]
(...)
at relational (angular.min.js:234)
at r.equality (angular.min.js:233)
at r.logicalAND (angular.min.js:233) "<a href="" ng-click="numbers.forEach(function(v) {v.selected=true;});">"
Plunker demo:
https://plnkr.co/edit/6OZP02SZ5ZYa0iO4PBY3?p=preview
Can I implement that just in the html template or have to use the controller method?
Edit: Controller method works fine, I'm just still interested why in-place code doesn't parse though?

Try like below, numbers.forEach(function(v) {v.selected=true;}); is wrong will throw the error because numbers doesn't have forEach menthod and anonymous function will not work in ng-click
This is the best way to perform select all
<div ng-app="myApp" ng-controller="myCtrl">
<label>
<input type="checkbox" ng-model="all">
Select All
</label>
<p ng-repeat='n in numbers'>
<label>
<input type="checkbox" ng-checked="all">
Label: {{ n.v }}
</label>
</p>
</div>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.numbers = [{v:1},{v:2},{v:3},{v:4}];
});
https://fiddle.jshell.net/mspj0z65/1/
HTML
<div ng-app="myApp" ng-controller="myCtrl">
select All
<p ng-repeat='n in numbers'>
<label>
<input type="checkbox" ng-model="n.selected">
Label: {{ n.v }}
</label>
</p>
</div>
Angular script:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.numbers = [{v:1},{v:2},{v:3},{v:4}];
$scope.loop = function(){
angular.forEach(numbers, function(v) {
v.selected=true;
});
}
});
https://fiddle.jshell.net/mspj0z65/

It is better implements the method on controller as:
$scope.selectAll=function() {
$scope.numbers.forEach(function(v) {
v.selected=true
});
}
and in view use ng-click="selecAll()"
Let your view as simple as posible and make the code more readable ans ease to
understand by third parties or own in the future.
I recomend take a view to John Papa Angular style guide

Related

angularjs: can't dynamically set filter method with scope data

In my angular application, I came into a filter related issue. I have reproduced this issue with a simple live demo as bellow:
https://jsfiddle.net/baoqger/fpo3j6gx/2/
<div ng-app="app">
<div ng-controller="filterCtrl as f">
<input type="text" ng-model="f.inputdata"></input>
<span ng-click="f.setFilter('lowercase')">First Filter</span>
<span ng-click="f.setFilter('uppercase')">Second Filter</span>
<div ng-bind="f.inputdata | f.filtername"></div>
</div>
click First Filter or Second Filter will trigger the setFilter function.
function filterCtrl() {
this.setFilter = function ( name ){
this.filtername = name;
}.bind(this);
}
angular
.module('app', [])
.controller('filterCtrl', filterCtrl)
In the controller, the filtername will be set to lowercase or upper case, depends on which button was clicked as mentioned above.
Then set the filtername as filter method as below:
<div ng-bind="f.inputdata | f.filtername"></div>
But based on the error message, it seems that angular system can't support such usage. Any help?
Try this solution:
Javascript:
.controller('filterCtrl', ['$filter' function($filter){
var self = this;
self.setFilter = function(name){
self.filter = $filter(name);
}
}]);
HTML:
<div ng-app="app">
<div ng-controller="filterCtrl as f">
<input type="text" ng-model="f.inputdata"></input>
<span ng-click="f.setFilter('lowercase')">First Filter</span>
<span ng-click="f.setFilter('uppercase')">Second Filter</span>
<div ng-bind="f.filter?f.filter(f.inputdata):f.inputdata"></div>
</div>

How to detect checkbox clicked in AngularJS?

I am using a javascript UI library as DHTMLX or YUI etc.
And I am using AngularJS to process dynamic page.
What I need is just simple.
UI code is
...
<Input type="checkbox" name="XXX" />
....
My.js
...
app.controller('XXXCtrl', function($scope){
$scope.$watch(???){
if (XXX) console.log("checkbox was checked!!!");
else console.log("checkbox was unchecked!!!");
????
};
})
I am new to AngularJS. Please help me!!!
You have to bind the value to the scope via ng-model. There is more detail in the documentation, but you can do something like that:
$scope.checkboxModel = true;
$scope.myAction = function () {
msg = $scope.checkboxModel ? 'checked' : 'unchecked';
console.log(msg);
};
And in your HTML file:
<form name="myForm" ng-controller="XXXCtrl">
<label>Value1:
<input type="checkbox" name="XXX" ng-model="checkboxModel" ng-change="myAction()">
</label><br/>
<tt>value1 = {{checkboxModel}}</tt><br/>
</form>
You can access to the window object using document.getElementById combined with ng-click event listener
var app = angular.module('myApp', []);
app.controller('appCtrl', function($scope) {
$scope.checker= function(e){
var chkBox = document.getElementById(e.target.id);
console.log(chkBox.checked)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='myApp'>
<div ng-controller='appCtrl'>
<input type="checkbox" id="myCheckbox" name="myCheckbox" ng-click="checker($event)"/>
</div>
</div>

AngularJS, ng-repeat on radio and $scope.watch

I'm using this example: https://jsfiddle.net/qnw8ogrk/1/ to create my radio-buttons.
I would like to be able to use $scope.watch on the radio-buttons, but I'm not able to use:
$scope.watch('selected', ...
What should I assign to .watch to be able to detect whenever a user clicks on a radio button?
Actual mistake was $scope.watch should be $scope.$watch Having watcher over a scope variable would not be the good idea. Instead of placing watcher over ng-model I'd suggest you to use ng-change which will only fires up when radio button ng-model value gets changed.
<label ng-repeat="option in options">
<input type="radio" ng-change="test()" ng-model="$parent.selected" ng-value="option" />{{option}}
</label>
And then don't use get rid of $parent notation for accessing outer scope of ng-repeat you could switch to use controllerAs pattern, and then change ng-controller directive to use alias of controller. Also that will change the controller implementation, bind value to this(context) instead of $scope
Markup
<div ng-controller="mainController as vm">
<label ng-repeat="option in vm.options">
<input type="radio" ng-change="vm.test()" ng-model="vm.selected" ng-value="option" />{{option}}
</label>
</div>
Controller
appModule.controller('mainController', function($scope) {
var vm = this;
vm.selected = 'red';
vm.options = ['red', 'blue', 'yellow', 'green'];
vm.test = function() {
alert('Changed');
}
});
Forked Plunkr
I agree with #PankajParker, but it is possible from you controller as well. You just got the syntax wrong, it is $scope.$watch, not $scope.watch
Have a look at this: https://jsfiddle.net/qnw8ogrk/32/
Fiddle: https://jsfiddle.net/stevenng/qnw8ogrk/33/
Markup
<div ng-app="app">
<div ng-controller="mainController">
<label ng-repeat="option in options">
<input type="radio" ng-change="picked(this)" ng-model="$parent.selected" ng-value="option"/>{{option}}
</label>
</div>
</div>
Script
var appModule = angular.module('app', []);
appModule.controller('mainController', function($scope) {
$scope.selected = 'red';
$scope.options = ['red', 'blue', 'yellow', 'green'];
$scope.picked = function($scope) {
alert('you picked: ' + $scope.selected);
}
});

Creating array of object in view

I'm using .net mvc3 application with angular js. In my view i'm trying to create the input field with ng-model property. Suppose if i have the following code, how i have to add ng-model attribute?
#foreach(var item in Model.ListItem)
{
<input type="text" value="item.name" name="Model.ListItem[count].name" ng-model="???"/>
}
Please help me with this.
I don't like the idea of meshing with backend template, but this should work:
<script>
angular.module("YourApp", [])
.controller("YourController", function($scope) {
$scope.list = [];
#foreach(var item in Model.ListItem)
{
$scope.list.push({
name: "#item.name"
// add other properties if you like
});
}
});
</script>
<div ng-app="YourApp">
<div ng-controller="YourController">
<input ng-repeat="item in list" type="text" name="{{item.name}}" ng-model="item"/>
</div>
</div>

Advice on the correct use of ngModel

I' new to AngularJS and have a following ambiguity with usage of ngModel. I want to give to the user possibility to generate unlimited number of "name": "value" pairs. So I generating div with ng-repeat for every element from pair. Here is my html:
<div ng-app>
<div ng-controller="TestCtrl">
<input type="button" value="+" ng-click="addNewRow();"/>
<div ng-repeat="a in range(itemsNumber)"><input type="text" name="key"/> : <input type="text" name="value"/></div>
</div>
</div>
And the JavaScript:
function TestCtrl($scope) {
$scope.itemsNumber = 1;
$scope.range = function() {
return new Array($scope.itemsNumber);
};
$scope.addNewRow = function () {
$scope.itemsNumber++;
}
};
Here is working js fiddle:
http://jsfiddle.net/zono/RCW2k/
I want to have model for this generating items but not sure how to do it.
I would appreciate any ideas and tips.
Best regards.
Edit:
I have create other solution. It can be viewed in this fiddle
http://jsfiddle.net/zono/RCW2k/8/
But is this solution is good idea?
Here is a fiddle: http://jsfiddle.net/RCW2k/13/
You should just create an array on the scope and it's also your model:
controller:
function TestCtrl($scope) {
$scope.items = [{key:"hello",value:"world"}]
$scope.addNewRow = function () {
$scope.items.push({key:"",value:""});
}
};
html:
<div ng-controller="TestCtrl">
<input type="button" value="+" ng-click="addNewRow();"/>
<div ng-repeat="item in items">
<input type="text" name="key" ng-model="item.key"/> :
<input type="text" name="value" ng-model="item.value"/>
</div>
</div>

Resources