How can we disable other checkboxes by clicking a checkbox from a list in Angular2 - checkbox

I have an list of checkboxes. In this I want to disable other checkboxes When I have checked any item from list. Now if I uncheck that item then now all checkboxes need to be enabled.
This is the plunker - http://plnkr.co/edit/5FykLiZBQtQb2b31D9kE?p=preview
On unchecking any checkbox all the rest checkboxes are still disabled. How can I do this?
This is app.ts file -
import {bootstrap} from 'angular2/platform/browser';
import {Component} from 'angular2/core'
#Component({
selector: 'my-app',
template: `
<h2>{{title}}</h2>
<label *ngFor="let cb of checkboxes">
{{cb.label}}<input [disabled]="cb.status" type="checkbox"
[(ngModel)]="cb.state" (click)="buttonState(cb.id)">
</label><br />
{{debug}}
`
})
class App {
title = "Angular 2 - enable button based on checkboxes";
checkboxes = [{label: 'one',id: '0', status: ''},{label: 'two', id: '1', status:''},{label: 'three', id: '2', status: ''}];
constructor() {
//this.buttonState();
console.log("constructor called"); }
buttonState(id) {
console.log( id + "Button State Called");
//return this.checkboxes[0].status;
if(this.checkboxes[id].state == true){
this.checkboxes[id].status = true;
this.checkboxes[(id+1)%3].status = false;
this.checkboxes[(id+2)%3].status = false;
console.log("True Block");
}
else (this.checkboxes[id].state == false) {
this.checkboxes[id].status = false;
this.checkboxes[(id+1)%3].status = true;
this.checkboxes[(id+2)%3].status = true;
console.log("False Block");
}
}
get debug() {
return JSON.stringify(this.checkboxes);
}
}
bootstrap(App, [])
.catch(err => console.error(err));

Use this buttonState function instead yours:
buttonState(id) {
this.checkboxes.forEach(function(checkbox) {
if (checkbox.id !== id) {
checkbox.status = !checkbox.status;
}
})
}
see plunker example: http://plnkr.co/edit/ASzUR2jawpbifvwBXNO9?p=preview

another solution..not a good one...but still you can try it if you find any problem
class App {
title = "Angular 2 - enable button based on checkboxes";
checkboxes = [{label: 'one',id: '0', status: ''},{label: 'two', id: '1', status:''},{label: 'three', id: '2', status: ''}];
constructor() {
console.log("constructor called");
}
buttonState(id) {
console.log( this.checkboxes[id].state + "Button State Called");
//return this.checkboxes[0].status;
if(this.checkboxes[id].state == true ){
this.checkboxes[id].status = false;
this.checkboxes[(id+1)%3].status = false;
this.checkboxes[(id+2)%3].status = false;
console.log("True Block");
}
else if(this.checkboxes[id].state == false || this.checkboxes[id].state == undefined) {
this.checkboxes[id].status = false;
this.checkboxes[(id+1)%3].status = true;
this.checkboxes[(id+2)%3].status = true;
console.log("False Block");
}
}
http://plnkr.co/edit/mAvSQbyP9oh84LWfpGIm?p=preview

Related

When checkbox is uncheck, I want to return all my list

when I uncheck my text box, its not returning an selectedItemsList
.Hope you understand my problem.
changeSelection() {
this.checkedIDs = []
this.selectedItemsList = this.DisplayProductList.filter((value, index) => {
if (value.isChecked == true) {
return value.isChecked
}
else{
this.selectedItemsList = this.ProductData;
}
});
this.router.navigate(['pipeline/cluster/policies'])
this.sendclusteridApi()
}
if (value.isChecked == false){
this.selectedItemsList = this.ProductData;
}
else{
this.selectedItemsList = this.ProductData;
}
You are definitely wrong here. Doing the same thing in if and else conditions.
Make changes to this code as you need, follow same structure:
HTML:
<mat-checkbox (click)="showData()" (checked)="(isChecked)" (change)="isChecked = !isChecked"></mat-checkbox>
<!-- below part only to visually see the change -->
<div *ngFor="let elem of displayedItems">
<p>{{ elem.name }}</p>
</div>
Typescript:
displayedItems = [];
selectedItemsList = [
{
item1: 'hello',
name: 'item1',
},
{
item2: 'hello',
name: 'item3',
},
{
item3: 'hello',
name: 'item3',
},
];
showData() {
if (this.isChecked === false) {
this.displayedItems = this.selectedItemsList;
} else {
this.displayedItems = [];
}
}

knockout - header checkbox stays unchecked in table header when clicked

I am new to knockout and I am stuck at a problem for last couple of days - I am sure it is something silly but cant figure out. Any help will be appreciate.
I am trying to select and deselect all rows in a table based on the header check box column. The SelectAll function works and selects/unselects all rows in table but the header remains unckecked?
<tr>
<th><input type="checkbox" data-bind="click: selectAll, checked: AllChecked"></th>
<th>#Html.Vocab("Document")</th>
<th>#Html.Vocab("Notes")</th>
<th>#Html.Vocab("Created")</th>
</tr>
<tbody data-bind="foreach: DocumentRows">
<tr >
<td><input type="checkbox" data-bind="checked: IsSelected"></td>
<td><data-bind="text: Notes"></td>
</tr>
</tbody>
And here is the script:
//Document
class Document {
Id: KnockoutObservable<number>;
Notes: KnockoutObservable<string>;
IsSelected: KnockoutObservable<boolean>;
constructor(data?) {
this.Id = ko.observable(0);
this.Notes = ko.observable("").extend({ defaultValue: "" });
this.IsSelected = ko.observable(false);
if (data != null) {
ko.mapping.fromJS(data, {}, this);
}
}
};
//DocumentS VIEW MODEL
class DocumentsViewModel {
DocumentRows: KnockoutObservableArray<Document>;
IsAnySelected: KnockoutObservable<boolean>;//used for delete button
constructor(params) {
this.DocumentRows = ko.observableArray([]);
this.selectedIds = ko.observableArray([]);
}
InitComputed = () => {
this.AllChecked= ko.pureComputed({
read: function () {
return this.selectedIds().length === this.DocumentRows().length;
},
write: function (value) {
this.selectedIds(value ? this.DocumentRows.slice(0) : []);
},
owner: this
}
this.IsAnySelected = ko.pureComputed(() => {
var isChecked = false;
ko.utils.arrayForEach(this.DocumentRows(), function (item) {
if (item.IsSelected()) {
isChecked = true;
}
});
return isChecked;
});
}
selectAll = (): void => {
if (this.selectedIds().length > 0) {
this.selectedIds.removeAll();
ko.utils.arrayForEach(this.DocumentRows(), function (item) {
item.IsSelected(false);
});
} else {
ko.utils.arrayPushAll(this.selectedIds(), this.DocumentRows())
ko.utils.arrayForEach(this.DocumentRows(), function (item) {
item.IsSelected(true);
});
}
}
}

indexOf comparing two lists, not matching exact values

Alright, so i have a list of checkmark forms, and upon clicking them, i submit an event and put all checked boxes values into a list, i then compare that list with another list to changes the matching checked values from true to false (using index of).
when i click canada, my console prints the expected output (Canada is true, United States and Mexico are false),
but then i click Mexico, so now Canada and Mexico have been selected, and all my countries turn to false.
i'm wondering if this is a problem with the way i'm implenting index of, or is it the order of calling functions that is causing this? a checked box should return true.
component:
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl } from '#angular/forms';
#Component({
selector: 'app-geo-drop',
templateUrl: './geo-drop.component.html',
styleUrls: ['./geo-drop.component.css']
})
export class GeoDropComponent implements OnInit {
selectedItems: any [] = [];
places = [
{ code: 'US', allow: 'true', name: 'United States', continent: 'North America' },
{ code: 'CA', allow: 'true', name: 'Canada', continent: 'North America' },
{ code: 'MX', allow: 'false', name: 'Mexico', continent: 'North America' }
];
countriesForm: FormGroup;
constructor() { }
ngOnInit() {
// add checkbox for each country
this.countriesForm = new FormGroup({});
for (let i = 0; i < this.places.length; i++) {
this.countriesForm.addControl(
this.places[i].name, new FormControl(false)
)
}
}
allow(selectedPlaces: Array<any>, allPlaces: Array<any>) {
allPlaces.filter(function (place) {
if (place.name.indexOf(selectedPlaces) > -1) {
place.allow = true;
} else {
place.allow = false;
};
});
this.places.forEach(item => {
console.log(item.name, item.allow);
});
}
search(place, event) {
let index = this.selectedItems.indexOf(place.name);
if (event.target.checked) {
if (index === -1) {
this.selectedItems.push(place.name);
console.log(this.selectedItems);
}
} else {
if (index !== -1) {
this.selectedItems.splice(index, 1);
console.log(this.selectedItems);
}
}
this.allow(this.selectedItems, this.places);
}
}
html
<div class="geo-list">
<div class="content-box container">
<form [formGroup]="countriesForm">
<div class="place" *ngFor="let place of places">
<input
type="checkbox"
formControlName="{{place.name}}"
(change)="search(place, $event)"
>
{{ place.name }} | {{ place.code }} | {{ place.continent }}
</div>
</form>
</div>
</div>
The answer is in your own debug info; you're asking the index of "Canada, Mexico"
Since none of your countries are called "Canada, Mexico", they're false.
You need to loop through all selected boxes in your html to fix it.
I found a simple solution. though i don't believe it's the fastest, if a faster method is known, please post it. this method changes the value directly on every (change), and then binds the checkbox to the current value of allowed
comp.
export class GeoDropComponent implements OnInit {
places = [
{ code: 'US', allow: true, name: 'United States', continent: 'North America' },
{ code: 'CA', allow: true, name: 'Canada', continent: 'North America' },
{ code: 'MX', allow: false, name: 'Mexico', continent: 'North America' }
];
countriesForm: FormGroup;
constructor() { }
// use ng on destroy to send final copy?
ngOnInit() {
// add checkbox for each country
this.countriesForm = new FormGroup({});
for (let i = 0; i < this.places.length; i++) {
this.countriesForm.addControl(
this.places[i].name, new FormControl(false)
)
}
}
search(place, event) {
for (let i = 0; i < this.places.length; i++) {
if (this.places[i].name === place.name) {
this.places[i].allow === true ? this.places[i].allow = false : this.places[i].allow = true;
}
}
console.log(place.allow);
console.log(this.places);
}
}
html
<input
type="checkbox"
formControlName="{{place.name}}"
value="{{place.allow}}"
(change)="search(place, $event)"
[checked]="place.allow"
>

Angularjs toolbar commands- disable and disable buttons

I am trying to disable and enable button:
for instance: If I click on Modify button I want to disable it and Enable Save button and if I click on Save button I want to enable Modify button and disable Save button. Thank you.
Below the Angularjs code:
angular.module('virtoCommerce.catalogModule')
.controller('virtoCommerce.catalogModule.categoriesItemsListController', ['$scope', function ($scope) {
var isFieldEnabled = true;
blade.updatePermission = 'catalog:update';
... (more codes but not included)
var formScope;
$scope.setForm = function (form) { formScope = form; }
//Save the prices entered by the user.
function savePrice()
{
//TODO: Save the price information.
}
function isDirty() {
return blade.hasUpdatePermission();
};
//function enablePriceField
function enablePriceField() {
var inputList = document.getElementsByTagName("input");
var inputList2 = Array.prototype.slice.call(inputList);
if (isFieldEnabled == true) {
for (i = 0; i < inputList.length; i++) {
var row = inputList2[i];
if (row.id == "priceField") {
row.disabled = false;
}
}
} else {
for (i = 0; i < inputList.length; i++) {
var row = inputList2[i];
if (row.id == "priceField") {
row.disabled = true;
}
}
}
//Set the flag to true or false
if (isFieldEnabled == true) {
isFieldEnabled = false
} else {
isFieldEnabled = true;
}
}
var formScope;
$scope.setForm = function (form) { formScope = form; }
function canSave() {
return isDirty() && formScope && formScope.$valid;
}
//Angular toolbar commands
blade.toolbarCommands = [
{
name: "platform.commands.modify",
icon: 'fa fa-pencil',
executeMethod: function () { enablePriceField();},
canExecuteMethod: function () { return true; }
},
{
name: "platform.commands.save",
icon: 'fa fa-floppy-o',
executeMethod: function () { savePrice(); },
canExecuteMethod: canSave,
permission: blade.updatePermission
}];
}]);
I am not sure I see how your code is related to the question, but you can enable/disable a button programatically using the ngDisabled directive (see the docs).
In your controller, intialize $scope.enableSave = true (of false, as you want). Then in your html:
<button class="btn btn-primary" ng-disabled="!enableSave" ng-click="enableSave=!enableSave">Save</button>
<button class="btn btn-primary" ng-disabled="enableSave" ng-click="enableSave=!enableSave">Modify</button>
You will toggle 'enableSave' each time you click on the active (ie. not disabled) button, which will in turn disable the button you just clicked, and enable the other one.
Sorry, I had not seen... I am not familiar with virtoCommerce, but if I understand correctly you want to update the 'canExecuteMethod' ? Maybe try something like that:
$scope.enableSave = false;
function canSave() {
return isDirty() && formScope && formScope.$valid && $scope.enableSave;
}
Then for the buttons:
{
name: "platform.commands.modify",
icon: 'fa fa-pencil',
executeMethod: function () {
enablePriceField();
$scope.enableSave = true;
},
canExecuteMethod: function () { return !canSave(); }
},
{
name: "platform.commands.save",
icon: 'fa fa-floppy-o',
executeMethod: function () {
savePrice();
$scope.enableSave = false;
},
canExecuteMethod: function () { return canSave(); },
permission: blade.updatePermission
}
As a side note, if isFieldEnabled is a boolean you can replace:
if (isFieldEnabled == true) {
isFieldEnabled = false
} else {
isFieldEnabled = true;
}
By: isFieldEnabled = !isFieldEnabled;

How can I fix this angular memory leak?

Here's my js
var app = angular.module('SearchAndResultsApp', ['angularUtils.directives.dirPagination']);
app.controller('SearchAndResultsController', function($location ,$scope, $http){
$scope.fields = [
{ id: 'accountNumber', name: 'Account Number', clicked: false},
{ id: 'pointOfInterestName', name: 'Point Of Interest Name', clicked: true},
{ id: 'address1', name: 'Address 1', clicked: false},
{ id: 'address2', name: 'Address 2', clicked: false},
{ id: 'city', name: 'City', clicked: false},
{ id: 'isostateCode', name: 'ISO State Code', clicked: false},
{ id: 'postalCode', name: 'Postal Code', clicked: false},
{ id: 'phone', name: 'Phone', clicked: false},
{ id: 'fax', name: 'Fax', clicked: false},
{ id: 'website', name: 'Website', clicked: false},
{ id: 'email', name: 'Email', clicked: false},
{ id: 'isocountryCode', name: 'ISO Country Code', clicked: false},
{ id: 'latitude', name: 'Latitude', clicked: false},
{ id: 'longitude', name: 'Longitude', clicked: false}
];
$scope.getSearchState = function() {
var fields = window.location.hash.substring(1).split("&");
if (fields.length > 0) {
return decodeURIComponent(fields[0]);
} else {
return '';
}
};
$scope.getPageState = function() {
var fields = window.location.hash.substring(1).split("&");
if (fields.length > 1) {
return parseInt(fields[1]);
} else {
return 1;
}
};
$scope.noResults = false;
$scope.pointsOfInterest = null;
$scope.loadingQuery = false;
$scope.orderDirection = 'asc';
$scope.glyphDirection = 'glyphicon-triangle-top';
$scope.orderedBy = 'pointOfInterestName';
$scope.previousClicked = $scope.fields[1];
$scope.lowerRange = 0;
$scope.upperRange = 0;
$scope.totalRange = 0;
$scope.currentPage = $scope.getPageState();
$scope.searchString = $scope.getSearchState();
$scope.offset = 'col-sm-offset-4';
$scope.loadingOffset = 'col-sm-offset-1';
$scope.getResultsState = function() {
return ((($scope.pointsOfInterest == null)||($scope.pointsOfInterest[0] == null)) && ($scope.searchString != ''))
};
$scope.downloadCSV = function(selection) {
if (selection == 'searched') {
window.location = 'pointsOfInterest/' + encodeURIComponent($scope.searchString) + '/orderedList/' + $scope.orderedBy + '/' + $scope.orderDirection + '/csv';
} else if (selection == 'all') {
if (confirm("This may take some time.")){
window.location = 'allPointsOfInterest/csv';
}
}
};
$scope.updateRanges = function() {
$scope.searchString = $scope.searchString = $scope.searchString.replace(/\//g,'').replace(/\\/g,'');
window.location.hash = encodeURIComponent($scope.searchString) + '&' + encodeURIComponent($scope.currentPage);
if ($scope.pointsOfInterest[0] != null) {
$scope.lowerRange = ($scope.currentPage - 1) * 20 + 1;
$scope.totalRange = $scope.pointsOfInterest.length;
$scope.upperRange = $scope.currentPage * 20;
} else {
$scope.lowerRange = 0;
$scope.totalRange = 0;
$scope.upperRange = 0;
}
if ($scope.upperRange > $scope.totalRange) {
$scope.upperRange = $scope.totalRange;
}
};
$scope.updateGlyphs = function(field) {
$scope.searchString = $scope.searchString = $scope.searchString.replace(/\//g,'').replace(/\\/g,'');
$scope.orderedBy = field.id;
if ($scope.previousClicked != null)
$scope.previousClicked.clicked = false;
field.clicked = true;
if ($scope.previousClicked == field) {
if ($scope.orderDirection == 'asc') {
$scope.orderDirection = 'desc';
$scope.glyphDirection = 'glyphicon-triangle-bottom';
} else {
$scope.orderDirection = 'asc';
$scope.glyphDirection = 'glyphicon-triangle-top';
}
} else {
$scope.orderDirection = 'asc';
$scope.glyphDirection = 'glyphicon-triangle-top';
}
$scope.updatePointsOfInterest();
$scope.previousClicked = field;
};
$scope.updatePointsOfInterest = function() {
if ($scope.searchString.length != 0) {
$scope.loadingOffset = '';
$scope.currentPage = $scope.getPageState();
$scope.searchString = $scope.searchString.replace(/\//g,'').replace(/\\/g,'');
window.location.hash = encodeURIComponent($scope.searchString) + '&' + encodeURIComponent($scope.currentPage);
if ($scope.searchString == '') return;
$scope.loadingQuery = true;
$http.get('pointsOfInterest/' + encodeURIComponent($scope.searchString) + '/orderedList/' + $scope.orderedBy + '/' + $scope.orderDirection)
.success(function(data) {
$scope.pointsOfInterest = data;
$scope.loadingQuery = false;
$scope.loadingOffset = 'col-sm-offset-1';
$scope.updateRanges();
$scope.noResults = $scope.getResultsState();
if ($scope.pointsOfInterest.length > 0) {
$scope.offset = '';
} else {
$scope.offset = 'col-sm-offset-4';
}
})
.error(function(data) {
window.location = 'pointsOfInterest/' + encodeURIComponent($scope.searchString) + '/orderedList/' + $scope.orderedBy + '/' + $scope.orderDirection;
});
}
};
window.onhashchange = function() {
$scope.updatePointsOfInterest();
}
$scope.updatePointsOfInterest();
$scope.gotoUpdatePage = function (accountNumber) {
window.location.href = 'pointOfInterestEditor/' + accountNumber;
};
$scope.onTextClick = function ($event) {
$event.target.select();
};
});
app.directive('ngDelay', ['$timeout', function ($timeout) {
return {
restrict: 'A',
scope: true,
compile: function (element, attributes) {
var expression = attributes['ngChange'];
if (!expression)
return;
var ngModel = attributes['ngModel'];
if (ngModel) attributes['ngModel'] = '$parent.' + ngModel;
attributes['ngChange'] = '$$delay.execute()';
return {
post: function (scope, element, attributes) {
scope.$$delay = {
expression: expression,
delay: scope.$eval(attributes['ngDelay']),
execute: function () {
var state = scope.$$delay;
state.then = Date.now();
$timeout(function () {
if (Date.now() - state.then >= state.delay)
scope.$parent.$eval(expression);
}, state.delay);
}
};
}
}
}
};
}]);
I get a memory leak from adding in the $location to the controller. I would like to use $location instead of window.location. I'm not sure why the memory leak is caused. Anyone know why and how to fix it?
Edit: It appears to be making infinite get requests. Still not sure how to fix it.
First of all $location service has a hash() method that u can use instead of window.location.hash().
Second: you call $scope.updatePointsOfInterest() method on your controller load that do a http get request. If it fails it changes the url. When the url is changed your controller code is reloaded, hence $scope.updatePointsOfInterest() method is executing again and again.
I'm not sure why $http.error() method is triggered. It could be anything. Check out your XHR request in Network tab in dev tools (Chrome).
If your $http.error() method should fail (this means that there's an error and it's properly handled) than to fix the "infinite looping" issue you can do the following:
1) either doesn't call $scope.updatePointsOfInterest() on controller loading
2) or doesn't change the url in your $http.error() method
If you describe what you're trying to achieve with this updatePointsOfInterest() method I will be able to help you write it properly.
Regards,
Aleksey

Resources