How to programmatically check checkbox with dynamic model name? - angularjs

I have created a some checkboxes with dynamic model name like this:
<label ng-repeat="item in main.itemDetails">
<input type="checkbox" checklist-value="item.price"
ng-click="itemChanged(item)" ng-model="checkboxes[item.name]">
{{item.name}} - <b>{{item.price}} €</b>
<br>
</label>
In my controller, I want to check some checkboxes if their model's name exists in array $scope.selectedItems.
I'm trying to do something like this but it isn't working:
for (var i = 0, j = $scope.selectedItems.length; i<j; i++) {
$scope['selectedItems[i].name'].isChecked = true;
}
for example if item.name = 'Item1' I want the model to be named $scope.Item1 and later I want to call $scope.Item1.isChecked = true;
What Am I doing wrong here?

Your are storing the model in the $scope.checkboxes, so you can set its value to true like the code below.
for (var i = 0, j = $scope.selectedItems.length; i<j; i++) {
$scope.checkboxes[$scope.selectedItems[i].name] = true;
}

It looks like your using a string literal here:
for (var i = 0, j = $scope.selectedItems.length; i<j; i++) {
$scope['selectedItems[i].name'].isChecked = true;
}
Just change this to read:
for (var i = 0, j = $scope.selectedItems.length; i<j; i++) {
$scope[selectedItems[i].name].isChecked = true;
}

var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.main = [{
'name':'test1',
'price':'23',
'isChecked':false
},
{
'name':'test2',
'price': '25',
'isChecked':false
},
{
'name':'test3',
'price': '21',
'isChecked':false
}];
$scope.selectedItems = [{
'name':'test1'
},
{
'name':'test2'
}];
angular.forEach($scope.main, function(valueMain){
angular.forEach($scope.selectedItems,function(valueSelected){
if(valueMain.name=== valueSelected.name){
valueMain.isChecked = true;
}
})
});
$scope.toggleCheck = function(item){
if(item.isChecked === true){
item.isChecked === false;
}else{
item.isChecked === true;
};
}
}
<script src="https://code.angularjs.org/angular-1.0.1.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<label ng-repeat="item in main">
<input type="checkbox" ng-model="item.isChecked" ng-checked="item.isChecked" ng-change="toggleCheck(item)">
{{item.name}} - <b>{{item.price}} €</b>
<br>
</label>
</div>
</div>
Angular Foreach is the easiest way to solve this kind of problem.

Related

Search a city using google map

I'm using a google map to show location in find search box (from that link) which is working fine:
angular.module('ui.bootstrap.demo').controller('TypeaheadCtrl',function($scope, $http) {
$scope.getLocation = function(val) {
return $http.get('//maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}).then(function(response){
return response.data.results.map(function(item){
return item.formatted_address;
});
});
};
<h4>Asynchronous results</h4>
<pre>Model: {{asyncSelected | json}}</pre>
<input type="text" ng-model="asyncSelected" placeholder="Locations loaded via $http" uib-typeahead="address for address in getLocation($viewValue)" typeahead-loading="loadingLocations" typeahead-no-results="noResults" class="form-control">
<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh"></i>
<div ng-show="noResults">
<i class="glyphicon glyphicon-remove"></i> No Results Found
</div>
I would like to know if possible to show my custom city near the search entry ?
Let's say I have bbCity, aaCity, ccCity and when a user types bb, her/him gets the nearest one (bbCity).
Thanks
I don't know if it's a right way but I solved it by adding the answer from this link.
angular.module('ui.bootstrap.demo').controller('TypeaheadCtrl',function($scope, $http) {
// Predefined areas
var predefinedLocations = [[48,68435270497298,4,39454410970211, 'city 1'],[48,33375503137806,5,616522543132305, 'city 2']];
$scope.getLocation = function(val) {
return $http.get('//maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}).then(function(response){
return response.data.results.map(function(item){
// Hold distances
var distances = [];
var start = new google.maps.LatLng(item.geometry.location.lat, item.geometry.location.lng);
for (var i = 0; i < predefinedLocations.length; i++)
{
var point = new google.maps.LatLng(predefinedLocations[i][0],predefinedLocations[i][1]);
var distance = google.maps.geometry.spherical.computeDistanceBetween(start, point);
distances.push(distance);
}
var firstElement = distances[0];
var index = 0;
for (var i = 1; i < distances.length; i++)
{
if(distances[i] < firstElement)
{
firstElement = distances[i];
index = i;
}
}
return predefinedLocations[index][2];
});
});
};

AngularJS: groups of checkboxes inside a loop

There are some categories inside ng-repeat, and each one includes some accounts, If each category is selected then all accounts inside it must be selected and vice versa. Also, if one account is not selected, then the parent category is not selected.
How can I do that?
Here is how the view is:
And the code fiddle:
http://jsfiddle.net/2f6qscrp/208/
Thank you for any help.
Here is the working fiddle for your case,
http://jsfiddle.net/balasuar/2f6qscrp/209/
HTML
<div ng-app='home'>
<!-- App goes here -->
<md-content layout-padding ng-controller="MainCtrl as mainCtrl">
<md-checkbox ng-model="selectedAll"
ng-change="toggleAll()"
class="md-primary">
<span ng-if="selectedAll">Un-</span>Select All
</md-checkbox>
<div ng-repeat="category in naturalAccounts">
<md-checkbox class="md-primary" ng-model="category.selected" ng-change="toggleCategory(category)">
{{ category.name }}
</md-checkbox>
<div ng-repeat="acc in category.accounts">
<md-checkbox class="md-primary" ng-model="acc.selected" ng-change="toggleAccount(category, acc)" >{{acc.name}}</md-checkbox>
</div>
</div>
</md-content>
</div>
JS
angular.module('home', ['ngAria', 'ngAnimate', 'ngMaterial']);
angular.module('home').config(function ($mdThemingProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('pink')
.accentPalette('grey');
});
angular.module('home').controller('MainCtrl', function ($scope) {
$scope.naturalAccounts = [
{"id":0,"name":"category0","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] },
{"id":1,"name":"category1","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] },
{"id":2,"name":"category2","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] }
];
$scope.selectedAll = false;
function setSelectedAll() {
for(var i = 0; i < $scope.naturalAccounts.length; i++) {
var category = $scope.naturalAccounts[i];
$scope.selectedAll = category.selected;
if(!$scope.selectedAll) {
break;
}
}
}
$scope.toggleAll = function() {
for(var i = 0; i < $scope.naturalAccounts.length; i++) {
var category = $scope.naturalAccounts[i];
category.selected = $scope.selectedAll;
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
account.selected = $scope.selectedAll;
}
}
};
$scope.toggleCategory = function(category) {
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
account.selected = category.selected;
}
setSelectedAll();
};
$scope.toggleAccount = function(category, account) {
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
category.selected = account.selected;
if(!category.selected) {
break;
}
}
setSelectedAll();
};
});
<input type="checkbox" ng-model="category.checked" ng-change="checkAllAccountsOfCategoryIfChecked(category)" />
and
<input type="checkbox" ng-model="account.checked" ng-change="checkOrUncheckCategoryBasedOnItsAccounts(category)" />
In your controller:
$scope.checkAllAccountsOfCategoryIfChecked = function(category) {
// TODO if category is checked, then loop over all its accounts and check them
}
$scope.checkOrUncheckParentCategory = function(category) {
// TODO if all the category's accounts are checked,
// then check the category, otherwise uncheck it
}

increment variable when checkbox is checked - angular

I want the $scope.selectedRecords variable to increment when a checkbox is checked. Right now nothing appears to happen, meaning the {{selectedRecords}} doesn't increment. There is no change.
Controller:
$scope.selectedRecords = 0;
// SET-UP ROW CLICK FOR CHECKBOX
$scope.setSelected = function(record) {
if (!record.Selected) {
record.Selected = true;
$scope.selectedRecords += 1
} else {
record.Selected = false;
$scope.selectedRecords -= 1
}
}
HTML:
<h4>{{selectedRecords}} users selected</h4>
<tr ng-repeat="record in records | orderBy:sortType:sortReverse | filter:searchUsers" ng-class="class" class="row-link" ng-click="setSelected(record)">
<input type="checkbox" ng-model="record.Selected" ng-click="setSelected(record)">
Here's a working example : http://codepen.io/anon/pen/pjNWVL?editors=101
Can't really understand why your sample doesn't work, but mine might give you some help :-)
HTML :
<div ng-app="pouet" ng-controller="PouetCtrl">
<h4>{{selectedRecords}} users selected</h4>
<div ng-repeat="record in records">
<input type="checkbox" ng-model="record.selected" ng-click="setSelected(record)">
<span class="label">{{record.label}}</span>
</div>
</div>
JS :
var mod;
mod = angular.module('pouet', []);
mod.controller('PouetCtrl', function($scope) {
$scope.records = [
{
selected: false,
label: 'foo'
}, {
selected: true,
label: 'bar'
}, {
selected: true,
label: 'baz'
}
];
$scope.selectedRecords = ($scope.records.filter(function(record) {
return record.selected;
})).length;
$scope.setSelected = function(record) {
if (record.selected) {
record.Selected = true;
$scope.selectedRecords += 1;
} else {
record.selected = false;
$scope.selectedRecords -= 1;
}
};
});
The problem is that you have not defined record on the scope. If you add something like this to your controller:
$scope.record = {};
Then things should work.
Now, if you are in an ng-repeat block, things will be more complicated.

angular filtered dropdown model not updating

I'm trying to update a filtered dropdowns(combobox) model on click of a button. The model value is changing but dropdown still shows an empty selected option. If I remove the filter everything works as it should (without filtering of course).
Plunker: http://plnkr.co/edit/a48JSEiiATrkcQKxfJjx?p=preview
JS:
$scope.tasks = [
{name:'Task1', taskid: 1, custid: 2},
{name:'Task2', taskid: 2, custid: 2},
{name:'Task3', taskid: 3, custid: 3}
];
$scope.myinfo = {};
$scope.updateinfo = {name:'Cust Name', custid: 3, taskid: 3};
$scope.setMyinfo = function(){
$scope.myinfo = $scope.updateinfo;
};
});
app.filter('taskFilter', function() {
return function(input, criteria) {
var result = [];
for (var i = 0; i < input.length; i++) {
if(input[i].custid == criteria || input[i].custid === undefined){
result.push(input[i]);
}
}
return result;
}
HTML:
<button ng-click="setMyinfo()">Button</button>
<br> <br>
Filtered:
<select ng-model="myinfo.taskid">
<option>---</option>
<option ng-repeat="task in tasks | taskFilter:myinfo.custid" value="{{task.taskid}}">{{task.name}}</option>
</select>
Unfiltered:
<select ng-model="myinfo.taskid">
<option>---</option>
<option ng-repeat="task in tasks" value="{{task.taskid}}">{{task.name}}</option>
</select>
<br><br>
Value: {{myinfo.taskid}}
Thanks you for helping!
pre-filter the list by key and value:
<div ng-repeat="(k,v) in filterCustId(tasks)">
{{k}} {{v.pos}}
</div>
And on the Controller:
$scope.filterCustId = function(items) {
var result = {};
angular.forEach(items, function(value, key) {
if (!value.hasOwnProperty('custid')) {
result[key] = value;
}
});
return result;
}
From:
https://stackoverflow.com/a/14789258/4668696
Please update code following line
if(input[i].custid == criteria || input[i].custid === undefined){
by
if(input[i].custid == criteria || input[i].custid === undefined || criteria == undefined){

How to disable angular template trimming?

I'm trying to create a tree structure in the select element. I make indention by filter. As a result this indentation trims after output. Is that possible to disable trimming?
<select id="cat">
<option value="{{category.id}}" ng-repeat="category in categories">{{category | intent}}</option>
</select>
app.filter('intent', function() {
return function(category) {
var INTENT_SIZE = 4;
if (category == null) {
return '';
}
var result = "";
for (var i = 0; i < category.intent * INTENT_SIZE; i++) {
result += " ";
}
result += category.name;
return result;
};
})
For angular 2+ I use this pipe to 'untrim' template spaces :
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'untrim'
})
export class UntrimPipe implements PipeTransform {
transform(value: any, args?: any): any {
return typeof value === 'string' ? value.replace(/\s/g, ' ') : value;
}
}
Related:
Add space to <select> with ng-options
var app = angular.module('app', []);
app.filter('intent', function() {
return function(category) {
var INTENT_SIZE = 4;
if (category == null) {
return '';
}
var result = "";
for (var i = 0, len = category.intent * INTENT_SIZE; i < len; i++) {
result += String.fromCharCode(160);
}
result += category.name;
return result;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app'>
<div ng-init="categories = [{id: 0, name:'bob', intent: 0},
{id: 1, name:'chris', intent: 1},
{id: 2, name:'mike', intent: 2}]"></div>
<select id="cat">
<option value="{{category.id}}" ng-repeat="category in categories">
{{ category | intent }}
</option>
</select>
</div>
You need to use the HTML character to render a space that will not be ignored by the browser.
But then you need to make sure that Angular "trusts" the HTML you are trying to use.
You can accomplish that by changing your markup to:
<select id="cat">
<option value="{{category.id}}" ng-repeat="category in categories" ng-bind-html="category | intent"></option>
</select>
Then change your filter code to:
app.filter('intent', function($sce) {
return function(category) {
var INTENT_SIZE = 4;
if (category == null) {
return '';
}
var result = "";
for (var i = 0; i < category.intent * INTENT_SIZE; i++) {
result += " ";
}
result += category.name;
return $sce.trustAsHtml(result);
};
});
Working Plunkr
NB: I only tested this in Chrome version 41. I'm not sure if all browsers allow having s in the option text.
To get space characters in your options use ng-bind-html to render the space.
<select id="cat">
<option value="{{category.id}}" ng-repeat="category in categories" ng-bind-html="category | intent"></option>
</select>
In your Filter:
app.filter('intent', function($sce) {
return function(category) {
var INTENT_SIZE = 4;
if (category == null) {
return '';
}
var result = "";
for (var i = 0; i < category.intent * INTENT_SIZE; i++) {
result += " ";
}
result += category.name;
return $sce.trustAsHtml(result);
};
});
DEMO

Resources