show checkbox elements of an array of checkboxes - angularjs

I have got a set of radiobuttons and an array of checkboxes. When i click radiobutton1 it should load first checkbox element from the array and when i click radiobutton2 it should load remaining 3 checkbox elements from the array.But it shows all 4 checkboxes in both the cases. I tried like this.
In HTML
<form>
<label class="radio-inline" >
<input value="1" type="radio" ng-model="radioption" >RB1</label>
<label class="radio-inline">
<input value="2" type="radio" ng-model="radioption" >RB2</label>
<div class="">
<label ng-repeat="channel in channels | filter:myFilter" >
<input type="checkbox" name="selectedChannels[]" value="{{channel.value}}"
ng-model="channel.selected" >{{channel.name}}
</label></div>
</form>
In Controller
App.controller('ReportController', ['$scope', 'Report', function($scope, Report){
var self = this;
$scope.channels = [{ name: 'A', selected: false, value: '1',visible:false },
{ name: 'B', selected: false, value: '2' ,visible:false},
{ name: 'C', selected: false, value: '3' ,visible:false},
{ name: 'D', selected: false, value: '4' ,visible:false}
];
$scope.selection = [];
$scope.selectedChannels = function selectedChannels() {
return Report($scope.channels, { selected: true } );
};
$scope.$watch('channels|filter:{selected:true}', function (new) {
$scope.selection = new.map(function (channel) {
return channel.value;
});
}, true);
$scope.myFilter = function(){
if ($scope.radioption == '1'){
return $scope.channels[0].visible = true;
}
else if ($scope.radioption == '2'){
return [$scope.channels[1],{ visible: true },
$scope.channels[2],{ visible: true },
$scope.channels[3],{ visible: true }];
}
});
}]);

I think you should approach this problem differently but if you want to use a filter try this
$scope.myFilter = function (channel) {
if ($scope.radioption == 1) {
if (channel.name == 'A') {
return true;
}
else {
return false;
}
}
else if ($scope.radioption == 2) {
if (channel.name == 'A') {
return false;
}
else {
return true;
}
}
else {
return false;
}
}
or you can add radioption column to channels array
$scope.channels = [{ name: 'A', selected: false, value: '1', radioption: 1 },
{ name: 'B', selected: false, value: '2', radioption: 2 },
{ name: 'C', selected: false, value: '3', radioption: 2 },
{ name: 'D', selected: false, value: '4', radioption: 2 }
];
and use ng-show
<input type="checkbox" ng-show="channel.radioption == radioption" name="selectedChannels[]" value="{{channel.value}}"
ng-model="channel.selected">{{channel.name}}

You need to register your filter with angularJS. e.g.
app.filter('myFilter', function() {
return function(input) {
var output;
// Do filter work here
return output;
}
Then you can use your filter in the HTML.
Also - filter should get input and return a filtered output. I think it make less sense to return a strict output regardless of the input given to it.
Take a look here, for example:
https://scotch.io/tutorials/building-custom-angularjs-filters

Related

Angular 8 Error "ERROR Error: "Cannot find control with name: 'getAccountArr'"" When using Form Array

I'm build in Angular 8 and I'm trying to render a list of inputs and prepopulate them with JSON data. I am using Reactive Forms for this project. The types array is being mapped correctly and being stored in the group fine. One of the things I am thinking it has something to do with the FormArrayName and where it is placed compared to the FormGroupName. I am wondering if I need to wrap the FormArray Name in the FormGroup Name.
view.ts
export class View2Component implements OnInit {
// public accountArr: FormArray;
public accounts: FormArray;
public accountForm: FormGroup;
types: any = [
{
name: "Assets",
display: {
default:'Display Value',
inputType:'input'
},
type: {
default:'type Value',
inputType:'selected',
data: ['a', 'b', 'c']
},
totalDesc: {
default:'totalDesc Value',
inputType:'input'
},
underlineBefore: {
default:'underlineBefore Value',
inputType:'input'
},
underlineAfter: {
default:'underlineAfter Value',
inputType:'input'
},
reverse: {
default: false,
inputType:'checkbox'
},
print: {
default: true,
inputType:'checkbox'
},
},
{
name: "Assets",
display: {
default:'Display Value',
inputType:'input'
},
type: {
default:'type Value',
inputType:'selected',
data: ['a', 'b', 'c']
},
totalDesc: {
default:'totalDesc Value',
inputType:'input'
},
underlineBefore: {
default:'underlineBefore Value',
inputType:'input'
},
underlineAfter: {
default:'underlineAfter Value',
inputType:'input'
},
reverse: {
default: false,
inputType:'checkbox'
},
print: {
default: true,
inputType:'checkbox'
},
}
];
get getAccountArr() { return this.accountForm.get('accounts') as FormArray; }
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.accountForm = this.fb.group({
accounts: this.fb.array([])
});
this.renderAccountForm();
console.log('accountArr', this.accountForm);
}
renderAccountForm() {
this.types.map(item => {
let val = this.fb.group({
display: [item.display.default],
type: [item.type.default]
});
this.getAccountArr.push(val);
});
}
}
view.html
<form [formGroup]="accountForm" novalidate>
<div formArrayName="getAccountArr" style="height:100px; margin:40px auto;">
<div *ngFor="let account of getAccountArr.controls; let i = index;">
<div [formGroupName]="i">
<h1 class="index-class">{{ i }}</h1>
<h1>{{ account.value.display }}</h1>
<input
type="text"
formControlName="{{ i }}"
[value]="account.value.display"
[placeholder]="account.value.displays"
/>
</div>
</div>
</div>
</form>
You are using getter incorrectly.
Replace get getAccountArr() { return this.accountForm.get('accounts') as FormArray; }
with get accounts() { return this.accountForm.get('accounts') as FormArray; }
and remove public accounts: FormArray;
get acts as an 'alias' and everytime you refer to this.accounts will return the FormArray.
You need to replace this line
<div formArrayName="getAccountArr" style="height:100px; margin:40px auto;">
with
<div formArrayName="accounts" style="height:100px; margin:40px auto;">
You need to give the name of the FormArray to formArrayName directive, and getAccountArr is not an exisiting form array in your form group, it's just a property that returns your form array which is different

Angularjs set checked radio not working

I have 3 radio buttons:
<label ng-repeat="mode in opMode.groupMode" class="radio-inline" title="{{mode.title}}">
<input id="rd{{mode.id}}" type="radio" class="panel-load-radio" ng-model="opdtMode.groupMode"
name="inlineRadioOptions" value="{{mode.id}}"
ng-change="changeOpdtMode(mode.id, '{{opdtMode.groupMode}}')">
{{mode.name}}
</label>
Here is Angularjs code:
$scope.opMode = { groupMode: [
{ name: "ModuleType", title: "Load processes by Module type", id: "ModuleType", isDefault: false },
{ name: "OpGroup", title: "Load processes by Operation group", id: "OpGroup", isDefault: true },
{ name: "MachineType", title: "Load processes by Machine type", id: "MachineType", isDefault: false }
]};
If isChange = true, show confirm mbox. If User click cancel, set oldValue and checked previous radio. I wrote this. However it's not working as expected:
$scope.changeOpdtMode = function (newValue, oldValue) {
if(isChange){
const msg = getMsgById(29, msgLostData);
const r = confirm(msg.value);
if (r === true) {
const lang = $scope.layoutLang.selectedLang;
loadLayout(null, lang, newValue);
window.isChange = false;
} else {
$scope.opdtMode.groupMode = oldValue;
}
}else{
const lang = $scope.layoutLang.selectedLang;
loadLayout(null, lang, newValue);
}
}
After 2 hours researched:
I post my answer here for everyone may see as the same issue.
<label ng-repeat="mode in opMode" class="radio-inline" title="{{mode.title}}">
<input type="radio" class="panel-load-radio" ng-value="mode.id"
ng-model="$parent.opdtMode" ng-change="changeOpdtMode(mode.id, '{{opdtMode}}')">
{{mode.name}}
</label>
Need to remove name="inlineRadioOptions" and add $parent into the model.
$scope.opdtMode = "OpGroup";
$scope.opMode = [{ name: "ModuleType", title: "Load processes by Module type", id: "ModuleType" },
{ name: "OpGroup", title: "Load processes by Operation group", id: "OpGroup" },
{ name: "MachineType", title: "Load processes by Machine type", id: "MachineType" }];
$scope.changeOpdtMode = function (newValue, oldValue) {
if(isChange){
const msg = getMsgById(29, msgLostData);
const r = confirm(msg.value);
if (r === true) {
const lang = $scope.layoutLang.selectedLang;
loadLayout(null, lang, newValue);
window.isChange = false;
} else {
$scope.opdtMode = oldValue;
}
}else{
const lang = $scope.layoutLang.selectedLang;
loadLayout(null, lang, newValue);
}
}

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.

angularjs custom filter vs selection lists

I have 6 select lists as the number of options i have and each has 6 options , when i select one options the rest of the section list must not contain the selected anymore
html
<div ng-repeat="filter in filters">
<select ng-model="selected" ng-options="item as item.type for item in filters|filterFnt:selected" ng-click="addProperty(selected)"></select>
js
$scope.selectionList = [] ;
$scope.selected = $scope.filters[0];
$scope.addProperty = function (obj) {
var index = $scope.selectionList.indexOf(obj);
if( index == -1) {
$scope.selectionList.push(obj);
}
};
$scope.filters = [
{
type : 'select one',
inputType : '111',
},
{
type : 'A',
inputType : '111',
},
{
type: 'B',
Xtype : '222'
},
{
type: 'C',
Xtype: '444' ,
},
{
type: 'D',
Xtype : '555'
},
{
type: 'E',
Xtype : '6666'
},
{
type: 'F',
inputType : '777'
}
];
app.filter('filterFnt', function() {
return function(input,x) {
angular.forEach($scope.selectionList, function(item) {
var index = input.indexOf(item);
if( index != -1 && item != x) {
input.splice(index, 1);
}
});
return input
};
});
issue
when i select an option from select list i want to keep that option in the list , what is happening it is being removed from the current one as well
Thank you
Your problem in splice function inside filter: it function change source array, so on every filter changed data for all selects.
Instead splice you can use simple filter function.
Your filter can be like
app.filter('filterFnt', function() {
return function(input, selectionList, selectionObj, filterType) {
//get elements that selected in current select, or not already selected
return input.filter(function(el) {
return selectionObj[filterType] === el || (selectionList.indexOf(el) == -1);
});
};
});
I add selectionObj, this object contain selected item for current select.
Before adding element in selectionList you need remove already added item from current select like
function removeFromSelected(currType){
var o = $scope.selectionObj[currType],
index = $scope.selectionList.indexOf(o);
if (index != -1)
$scope.selectionList.splice(index, 1);
}
var app = angular.module('app', []);
app.controller('ctrl', function($scope) {
function removeFromSelected(currType){
var o = $scope.selectionObj[currType],
index = $scope.selectionList.indexOf(o);
if (index != -1)
$scope.selectionList.splice(index, 1);
}
$scope.addProperty = function(obj, currType) {
removeFromSelected(currType);
if (!obj) {
delete $scope.selectionObj[currType];
} else {
var index = $scope.selectionList.indexOf(obj);
$scope.selectionList.push(obj);
$scope.selectionObj[currType] = obj;
}
};
$scope.filters = [{
type: 'A',
inputType: '111',
}, {
type: 'B',
Xtype: '222'
}, {
type: 'C',
Xtype: '444',
}, {
type: 'D',
Xtype: '555'
}, {
type: 'E',
Xtype: '6666'
}, {
type: 'F',
inputType: '777'
}];
$scope.selectionList = [];
$scope.selectionObj = {};
});
app.filter('filterFnt', function() {
return function(input, selectionList, selectionObj, filterType) {
return input.filter(function(el) {
return selectionObj[filterType] === el || (selectionList.indexOf(el) == -1);
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div ng-repeat="filter in filters">
<select ng-model="selected" ng-options="item as item.type for item in filters|filterFnt:selectionList:selectionObj:filter.type" ng-change="addProperty(selected,filter.type)">
<option value="">select one</option>
</select>
</div>
selectionList - {{selectionList}}
</div>

How to check if any Checkbox is checked in Angular

Is there any function or ng-something to check if any of the displayed Checkboxes are checked?
I have the values through the ng-click="function()" and pass the values through. I can go by foot and check my array if any value is inside.
I want to activate/deactivate the "next"-button if any Checkbox is
checked.
What's the easiest way?
If you don't want to use a watcher, you can do something like this:
<input type='checkbox' ng-init='checkStatus=false' ng-model='checkStatus' ng-click='doIfChecked(checkStatus)'>
You can do something like:
function ChckbxsCtrl($scope, $filter) {
$scope.chkbxs = [{
label: "Led Zeppelin",
val: false
}, {
label: "Electric Light Orchestra",
val: false
}, {
label: "Mark Almond",
val: false
}];
$scope.$watch("chkbxs", function(n, o) {
var trues = $filter("filter")(n, {
val: true
});
$scope.flag = trues.length;
}, true);
}
And a template:
<div ng-controller="ChckbxsCtrl">
<div ng-repeat="chk in chkbxs">
<input type="checkbox" ng-model="chk.val" />
<label>{{chk.label}}</label>
</div>
<div ng-show="flag">I'm ON when band choosed</div>
</div>
Working: http://jsfiddle.net/cherniv/JBwmA/
UPDATE: Or you can go little bit different way , without using $scope's $watch() method, like:
$scope.bandChoosed = function() {
var trues = $filter("filter")($scope.chkbxs, {
val: true
});
return trues.length;
}
And in a template do:
<div ng-show="bandChoosed()">I'm ON when band choosed</div>
Fiddle: http://jsfiddle.net/uzs4sgnp/
If you have only one checkbox, you can do this easily with just ng-model:
<input type="checkbox" ng-model="checked"/>
<button ng-disabled="!checked"> Next </button>
And initialize $scope.checked in your Controller (default=false). The official doc discourages the use of ng-init in that case.
Try to think in terms of a model and what happens to that model when a checkbox is checked.
Assuming that each checkbox is bound to a field on the model with ng-model then the property on the model is changed whenever a checkbox is clicked:
<input type='checkbox' ng-model='fooSelected' />
<input type='checkbox' ng-model='baaSelected' />
and in the controller:
$scope.fooSelected = false;
$scope.baaSelected = false;
The next button should only be available under certain circumstances so add the ng-disabled
directive to the button:
<button type='button' ng-disabled='nextButtonDisabled'></button>
Now the next button should only be available when either fooSelected is true or baaSelected is true and we need to watch any changes to these fields to make sure that the next button is made available or not:
$scope.$watch('[fooSelected,baaSelected]', function(){
$scope.nextButtonDisabled = !$scope.fooSelected && !scope.baaSelected;
}, true );
The above assumes that there are only a few checkboxes that affect the availability of the next button but it could be easily changed to work with a larger number of checkboxes and use $watchCollection to check for changes.
This is re-post for insert code also.
This example included:
- One object list
- Each object hast child list.
Ex:
var list1 = {
name: "Role A",
name_selected: false,
subs: [{
sub: "Read",
id: 1,
selected: false
}, {
sub: "Write",
id: 2,
selected: false
}, {
sub: "Update",
id: 3,
selected: false
}],
};
I'll 3 list like above and i'll add to a one object list
newArr.push(list1);
newArr.push(list2);
newArr.push(list3);
Then i'll do how to show checkbox with multiple group:
$scope.toggleAll = function(item) {
var toogleStatus = !item.name_selected;
console.log(toogleStatus);
angular.forEach(item, function() {
angular.forEach(item.subs, function(sub) {
sub.selected = toogleStatus;
});
});
};
$scope.optionToggled = function(item, subs) {
item.name_selected = subs.every(function(itm) {
return itm.selected;
})
$scope.txtRet = item.name_selected;
}
HTML:
<li ng-repeat="item in itemDisplayed" class="ng-scope has-pretty-child">
<div>
<ul>
<input type="checkbox" class="checkall" ng-model="item.name_selected" ng-click="toggleAll(item)"><span>{{item.name}}</span>
<div>
<li ng-repeat="sub in item.subs" class="ng-scope has-pretty-child">
<input type="checkbox" kv-pretty-check="" ng-model="sub.selected" ng-change="optionToggled(item,item.subs)"><span>{{sub.sub}}</span>
</li>
</div>
</ul>
</div>
<span>{{txtRet}}</span>
</li>
Fiddle: example
I've a sample for multiple data with their subnode
3 list , each list has attribute and child attribute:
var list1 = {
name: "Role A",
name_selected: false,
subs: [{
sub: "Read",
id: 1,
selected: false
}, {
sub: "Write",
id: 2,
selected: false
}, {
sub: "Update",
id: 3,
selected: false
}],
};
var list2 = {
name: "Role B",
name_selected: false,
subs: [{
sub: "Read",
id: 1,
selected: false
}, {
sub: "Write",
id: 2,
selected: false
}],
};
var list3 = {
name: "Role B",
name_selected: false,
subs: [{
sub: "Read",
id: 1,
selected: false
}, {
sub: "Update",
id: 3,
selected: false
}],
};
Add these to Array :
newArr.push(list1);
newArr.push(list2);
newArr.push(list3);
$scope.itemDisplayed = newArr;
Show them in html:
<li ng-repeat="item in itemDisplayed" class="ng-scope has-pretty-child">
<div>
<ul>
<input type="checkbox" class="checkall" ng-model="item.name_selected" ng-click="toggleAll(item)" />
<span>{{item.name}}</span>
<div>
<li ng-repeat="sub in item.subs" class="ng-scope has-pretty-child">
<input type="checkbox" kv-pretty-check="" ng-model="sub.selected" ng-change="optionToggled(item,item.subs)"><span>{{sub.sub}}</span>
</li>
</div>
</ul>
</div>
</li>
And here is the solution to check them:
$scope.toggleAll = function(item) {
var toogleStatus = !item.name_selected;
console.log(toogleStatus);
angular.forEach(item, function() {
angular.forEach(item.subs, function(sub) {
sub.selected = toogleStatus;
});
});
};
$scope.optionToggled = function(item, subs) {
item.name_selected = subs.every(function(itm) {
return itm.selected;
})
}
jsfiddle demo

Resources