Angular: How to uncheck all checkboxes with a link? - html

Here's my fiddle: http://jsfiddle.net/VSph2/280/
I'm trying to uncheck a checkbox and reset the values of a scope variable with a link, however, it doesn't seem to work. Could someone help?
Javascript:
var app = angular.module('myApp', []);
app.controller('IndexCtrl', ['$scope', function($scope) {
$scope.colors = [
{id: 1, name: "Blue"},
{id: 2, name: "Green"},
{id: 3, name: "Red"}
];
$scope.color_ids = [];
$scope.clearAll = function() {
angular.forEach($scope.color_ids, function(color_id) {
color_id.checked = false; //nothing works!!
color_id.selected = false; //
});
$scope.color_ids = [];
$scope.color_ids.selected = false; //doesn't work either
};
}]);
HTML:
<div ng-controller="IndexCtrl">{{1+1}}
<h2>Products</h2>
<div class="filters col-two">
<a ng-click="clearAll()">Clear all filters</a>
<h3>Color</h3>
<div ng-repeat="color in colors">
{{ color.name }} <input type="checkbox" ng-model="color_ids">
</div>
</div>
</div>

You never add anything to the color_id array, so the foreach is not iterating over anything.
I updated your code to just use the main color array and add a selected property on it:
http://jsfiddle.net/VSph2/283/
html:
{{ color.name }} <input type="checkbox" ng-model="color.selected">
javascript:
angular.forEach($scope.colors, function(color_id) {
color_id.selected = false;
});

I came across this while looking for something similar, my solution is to reset the color_ids object
$scope.clearAll = function() {
$scope.color_ids = [];
};
You also need to make the following changes to the input
<input type="checkbox" ng-model="color_ids[color.id]" ng-checked="color_ids[color.id]">
jsfiddle at
https://jsfiddle.net/novelnova/VSph2/756/

You are misunderstanding what ng-model on a checkbox does. It will only toggle a specific value set. So in your example, you would want to change it to:
{{ color.name }} <input type="checkbox" ng-model="color.selected">
And then your colors will have an additional attribute called selected that is either true or false, depending on if the box is checked or not.
To clear, you would then loop over all colors and set their selected state to false.
$scope.clearAll = function() {
angular.forEach($scope.colors, function(color) {
color.selected = false;
});
Updated fiddle: http://jsfiddle.net/VSph2/285/

Related

Angularjs - How to limit in ng repeat based on value

I am using angularjs here my div will come based on onchange of drop down.Here I need to limit the h4 tag to only once based on its value.if suppose my value is critical coming multiple times it should be only once again if my value is major coming multiple times it should be only once like that.these values are coming from json so it is dynamic.Can anyone please help am new to angularjs,here is the code below
html
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<select class="change" ng-model="x" ng-change="update()">
<option value="condition">condition</option>
</select>
<div class="main">
<div ng-repeat="emp in groups" ng-attr-id="{{emp[attr]}}">
<h4 id="test" class="{{emp[attr]}}">{{emp[attr]}}</h4>
</div>
</div>
</div>
script
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.groups = [
{
name: 'Malaria',
symptom:'fever',
categoty:'critical',
id:'1'
},
{
name: 'cancer',
symptom:'diesease',
categoty:'critical',
id:'3'
},
{
name: 'fever',
symptom:'diesease',
categoty:'major',
id:'3'
},
{
name: 'Cold',
symptom:'colds',
categoty:'major',
id:'2'
}
]
$scope.update = function() {
if($scope.x == 'condition'){
$scope.id='categoty';
$scope.attr = 'categoty';
}
}
});
You were a bit ambiguous when you say "is coming only once in the data". I think the behavior you are looking for in the shared plnkr is to allow the user to select an attribute and group by that attribute showing only the name property listed under the individual groupings.
To accomplish this, I built a selection of attributes the user can pick. So if a minor property is added to the objects in the future, it will continue to function and that can be added to the picker.
After picking an item, the data is parsed and it groups the items by the selected attribute. Each group is a key (selected attribute) mapping to an array (the item names). Once the grouping is made, two ng-repeats can display their data. The top level ng-repeat for each group category and the nested ng-repeat to show the items/names under the group.
var jsonData = [
{
name: 'Malaria',
symptom:'Fever',
category:'Critical',
id:'1'
},
{
name: 'Cancer',
symptom:'Diesease',
category:'Critical',
id:'3'
},
{
name: 'Fever',
symptom:'Diesease',
category:'Major',
id:'3'
},
{
name: 'Cold',
symptom:'Colds',
category:'Major',
id:'2'
}
];
// Setup angular
angular.module('myApp', [])
.controller('MainController', function MainController() {
var self = this;
// Setup your dropdown selections to choose an attribute
self.attrs = [
'category',
'symptom'
];
// On selection change, update how groups is built
self.onSelect = function onSelect(attr) {
// First build a map of all items grouped by attr
var groupMap = {};
jsonData.forEach(function group(item) {
var attrVal = item[attr],
arr = groupMap[attrVal];
if (!arr) {
arr = groupMap[attrVal] = [];
}
// Push the item name
arr.push(item.name);
});
self.groups = groupMap;
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.10/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainController as $ctrl">
Select Attribute:
<select ng-model="$ctrl.selectedAttr" ng-change="$ctrl.onSelect($ctrl.selectedAttr)">
<option ng-repeat="attr in $ctrl.attrs">{{::attr}}</option>
</select>
<div ng-show="::$ctrl.selectedAttr">
<div ng-repeat="(attr, names) in $ctrl.groups">
<h4>{{::attr}}</h4>
<ul>
<li ng-repeat="name in names">{{::name}}</li>
</ul>
</div>
</div>
</div>

Checkmarks don't show in checkbox on Window.print Angularjs

I am using AngularJs to display a few checkboxes. I have a click event which writes the current html to a window using document.write. However, when the new window opens for printing, none of the checkboxes are checked.
Here is the function which prints the document to the window:
$scope.printForm = function () {
var doc = document.getElementById('myForm').outerHTML;
var myWindow = $window.open('', '', 'width=1100, height=1000');
myWindow.document.write(doc);
myWindow.print();
};
Here is the HTML for the checkboxes:
`<div ng-repeat="c in f.Choices" >
<input type="checkbox" ng-disabled="true" ng-model="c.isSelected" /> {{c.vchDescription}} </div>`
Here is what it looks like BEFORE I click "printForm"
And here is what it looks like after I click "printForm":
Any assistance is greatly appreciated.
Mehod #1: generate HTML
Model is passed to print-button directive. It generates HTML and writes it to the opened window.
SO does not allow to open new windows. See working example on Plunkr.
Method #2: use CSS media queries
There's no need to open a new window. Just style document for print media accordingly.
angular.module('app', [])
.controller('AppController', function($window) {
this.options = [
{label: 'Foo', checked: false},
{label: 'Bar', checked: true}
];
// if you just need to print
this.print = function() {
$window.print();
};
})
// directive to generate HTML from model
.directive('printButton', function($window) {
return {
template: '<button ng-click="generate()">Open in new window</button>',
scope: {
data: '='
},
link: function(scope) {
scope.generate = function() {
var win = $window.open("", "bar", "width=200,height=100");
var html = '';
scope.data.forEach((val) => {
html += '<input type="checkbox"' + ((val.checked) ? ' checked=checked' : '') + '"/><label>'+val.label+'</label>';
})
win.document.write(html);
}
}
}
});
#media print {
.not-printable {
display: none;
}
}
<html ng-app="app" ng-controller="AppController as app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body>
<h1 class="not-printable">This will not be printed</h1>
<div ng-repeat="opt in app.options">
<input type="checkbox" ng-model="opt.checked" /><label ng-bind="opt.label"></label>
</div>
<div class="not-printable">
<div print-button data="app.options"></div>
<button ng-click="app.print()">Simply print</button>
</div>
</body>
</html>
Figured this one out by accident. Changing ng-model="c.isSelected" tp ng-checked="c.isSelected" allowed the checkmarks to show in the checkboxes.
Simple code change below solved it:
<div ng-repeat="c in f.Choices" >
<input type="checkbox" ng-disabled="true" ng-checked="c.isSelected" checked/> {{c.vchDescription}}
</div>

AngularJS - Multiple Dropdowns

I'm currently working on a project where I have a button that adds a dropdown everytime you click on the button.
Clicking the button not only shows the dropdown, but also a "Remove item" button, where you can remove the respective item added.
Then if you select an option from the dropdown, it will show another dropdown with more options, depending on what you chose on the first dropdown.
You can choose from the dropdown two options, movies or games.
And then on the second dropdown should appear a movie list or a game list depending on what you selected.
You can see HERE the current fiddle.
index.html:
<div ng-app="myApp" ng-controller="testCtrl">
<button ng-click = "addNewItem()">Add new Item</button>
<div ng-repeat="item in itemSet.item track by $index">
<button ng-click = "removeItem($index)">Remove item</button>
<select ng-model="category"
ng-change="changeCategory(category)"
ng-options="category as category for category in categoryTypes">
<option></option>
</select>
<select ng-show="movieSelected"
ng-model="movieType"
ng-options="movie as movie for movie in movieCategories">
<option></option>
</select>
<select ng-show="gameSelected"
ng-model="gameType"
ng-options="game as game for game in gameCategories">
<option></option>
</select>
</div>
</div>
app.js:
var myApp = angular.module('myApp', []);
myApp.controller('testCtrl', ['$scope', function ($scope) {
$scope.categoryTypes = ['Movies', 'Games'];
$scope.gameCategories = ['RPG', 'Sports'];
$scope.movieCategories = ['Action', 'SciFi'];
$scope.itemSet = { item : [] };
$scope.itemSet.item = [];
$scope.gameSelected = false;
$scope.movieSelected = false;
$scope.addNewItem = function () {
$scope.itemSet.item.push('');
};
$scope.removeItem = function (index) {
$scope.itemSet.item.splice(index, 1);
};
$scope.changeCategory = function(category) {
if(category == 'Movies') {
$scope.gameSelected = false;
$scope.movieSelected = true;
} else {
$scope.gameSelected = true;
$scope.movieSelected = false;
}
};
}]);
There are some things that are going wrong with this. With no order in particular:
For example, if I added 3 items, and then want to delete the first one, it will delete the third, then the second and finally the first if you keep pressing the "Remove Item" button.
If I add 3 items and I select "movies" from the first dropdown on the first row for example, it will display all of the other dropdowns with the possibility of choosing the items from the movie list on all of them, even if I didn't choose anything from the other rows.
Also if you want to add, lets say, 2 items, in one item you pick first "movies" and then on the second one you pick "games", the "extra" dropdowns will show the list of games instead of the respective list of items for each of the cases.
The actual project works similar to this, but with 4 dropdowns, and the information comes from a database but I guess that with the Fiddle should be enough to get the idea and to take a possible solution to the actual project.
If someone could help me out on this one I'll be very gratefull!
Your code has a big problem that is: you have the same ngModel for all items in ngRepeat.
After fixing this, you can simplify a lot your code.
You don't need to use ngChange to know what category is selected, you can simply use ngSwitch directive what fits well in this case.
See it working:
(function() {
'use strict';
angular
.module('myApp', [])
.controller('testCtrl', testCtrl);
testCtrl.$inject = ['$scope'];
function testCtrl($scope) {
$scope.categoryTypes = ['Movies', 'Games'];
$scope.gameCategories = ['RPG', 'Sports'];
$scope.movieCategories = ['Action', 'SciFi'];
$scope.itemSet = {
item: []
};
$scope.addNewItem = function() {
$scope.itemSet.item.push({});
};
$scope.removeItem = function(index) {
$scope.itemSet.item.splice(index, 1);
};
}
})();
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="testCtrl">
<button ng-click="addNewItem()">Add new Item</button>
<div ng-repeat="item in itemSet.item track by $index">
<button ng-click="removeItem($index)">Remove item</button>
<select ng-model="item.category"
ng-options="category for category in categoryTypes">
<option value hidden>Select a category</option>
</select>
<span ng-switch="item.category">
<select ng-switch-when="Movies"
ng-model="item.movie"
ng-options="movie for movie in movieCategories">
<option value hidden>Select a movie</option>
</select>
<select ng-switch-when="Games"
ng-model="item.game"
ng-options="game for game in gameCategories">
<option value hidden>Select a game</option>
</select>
</span>
</div>
<pre ng-bind="itemSet.item | json"></pre>
</div>
</body>
</html>
The main problem is you're controls are bound $scope values instead of the individual items you are trying to manipulate. A secondary problem is that you initialize each new array element as an empty string '' instead of an object {}.
This will work:
index.html
<div ng-app="myApp" ng-controller="testCtrl">
<button ng-click = "addNewItem()">Add new Item</button>
<div ng-repeat="item in itemSet.item track by $index">
<button ng-click = "removeItem($index)">Remove item</button>
<select ng-model="item.category"
ng-change="changeCategory(item)"
ng-options="category as category for category in categoryTypes">
<option></option>
</select>
<select ng-show="item.movieSelected"
ng-model="movieType"
ng-options="movie as movie for movie in movieCategories">
<option></option>
</select>
<select ng-show="item.gameSelected"
ng-model="gameType"
ng-options="game as game for game in gameCategories">
<option></option>
</select>
</div>
</div>
app.js
var myApp = angular.module('myApp', []);
myApp.controller('testCtrl', ['$scope', function ($scope) {
$scope.categoryTypes = ['Movies', 'Games'];
$scope.gameCategories = ['RPG', 'Sports'];
$scope.movieCategories = ['Action', 'SciFi'];
$scope.itemSet = { item : [] };
$scope.itemSet.item = [];
$scope.gameSelected = false;
$scope.movieSelected = false;
$scope.addNewItem = function () {
$scope.itemSet.item.push({});
};
$scope.removeItem = function (index) {
$scope.itemSet.item.splice(index, 1);
};
$scope.changeCategory = function(item) {
if(item.category == 'Movies') {
item.gameSelected = false;
item.movieSelected = true;
} else {
item.gameSelected = true;
item.movieSelected = false;
}
};
}]);
Updated fiddle:https://jsfiddle.net/5zwsdbr0/

Select all options from dropdown on button click using AngularJS

I want to select all values from a drop down of HTML on ng-click. Here is my HTML code
<select multiple ng-model="selectedToPostalCodes"
ng-options="items.postalcode for items in toPostalCodes">
<option style="display:none;"></option>
</select>
<input type="button" value="Select All" ng-click="selectall()">
So I want the implementation of selectall() function.
Thanks
you can try this way:: Fiddle
fiddleApp.controller('Main', ['$scope', function($scope) {
$scope.toPostalCodes = [
{postalcode:1, name:"Japan"},
{postalcode:4, name:"USA"}
];
$scope.selectedToPostalCodes = [];
$scope.selectall = function(){
$scope.selectedToPostalCodes = [];
angular.forEach($scope.toPostalCodes, function(item){
$scope.selectedToPostalCodes.push( item.postalcode);
});
}
}]);
You can try like this:
$scope.selectall = function() {
var allOptions = [];
// First get all codes as list
angular.forEach($scope.toPostalCodes, function(item) {
allOptions.push(item.postalcode);
});
// And then assign the values to the scope model
$scope.selectedToPostalCodes = allOptions;
};

multi instance of a custom polymer-element and javascript dom manipulation

I have created a custom polymer component that is a chat component. When a message is posted, a fake answer is published. Nothing very complicated.
Besides, when I instantiate two instances of my component, when I click on the enter button to post a message, the instance of the textfield used to get the text is not the good one.
I don't know if it is a problem of my code or the way I code the component or the regular behavior with polymer.
Please, let me know what is going wrong.
Best regads,
here the code:
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<!-- css import --> <!-- ... -->
<polymer-element name="chat-element">
<template>
<div class="chatview containerwindow" >
<div class="containertitle">
<span>CHAT VIEW</span>
</div>
<div class="chatcomponent">
<div id="messagecontainer" class="messagecontainer" >
</div>
<div class="footer">
<input type="text" class="inputtext" id="inputtextfield" />
<div class="insertchatbutton" id="insertchatbutton" >Enter</div>
</div>
</div>
</div>
</template>
<script>
Polymer('chat-element', {
myself: "",
inputextfiled: "",
insertchatbutton: "",
messagecontainer: "",
domReady: function() {
myself = this;
inputextfiled = this.$.inputtextfield;
inputextfiled.onkeyup = function(event) {
if (event.which == 13) {
myself.insertMessage(this);
}
};
insertchatbutton = this.$.insertchatbutton;
insertchatbutton.onclick = function() {
myself.insertMessage(inputextfiled);
};
messagecontainer = this.$.messagecontainer;
},
insertMessage : function (textview) {
var div = document.createElement('div');
div.classList.add('chatpushed');
var span = document.createElement('span');
span.innerHTML = textview.value;
div.appendChild(span);
messagecontainer.appendChild(div);
//scroll to the bottom
messagecontainer.scrollTop = messagecontainer.scrollHeight;
textview.value = "";
setTimeout(self.reply, 1000);
},
reply : function() {
var div = document.createElement('div');
div.classList.add('chatreceived');
var span = document.createElement('span');
span.innerHTML = "Message received";
div.appendChild(span);
messagecontainer.appendChild(div);
}
});
</script>
First off, here is a working version using more Polymer idioms:
http://jsbin.com/xokar/9/edit
Now, about some of the problems you are having. When you write
inputextfiled = this.$.inputtextfield
because you didn't use var you created a global variable. That means there is only one value of inputextfiled (sic) for the entire application.
You have to use this keyword to create and access instance variables, e.g., this.inputextfield.
You have a related problem here: setTimeout(self.reply, 1000);, because you instructed the timeout to call the self.reply function with window as this. You really want something like setTimeout(self.reply.bind(self)).
Here is some general information about this: http://www.quirksmode.org/js/this.html.