How can I ensure by default all by checkboxes (output from my data) are all checked by default on load?
Output checkbox
<div v-for="(category, index) in remove_category_duplicates" class="form-check">
<input type="checkbox" class="form-check-input" v-model="cat_data" :id="category" :value="category">
<label class="form-check-label">{{ category }}</label>
</div>
Setup checkbox values from data
remove_category_duplicates: function () {
// Get all categories and remove duplicates
let data = {}
this.info.forEach(i=>{
Object.assign(data,i.category_data);
})
return data;
},
Data:
{
"id": 1,
"title": "Title one",
"category_data": {
"2": "Team",
"7": "Queries"
}
},
CodePen: https://codepen.io/anon/pen/XxNORW?editors=1011
Thanks
To initialize the checkboxes to true/checked, their v-model array (cat_data) should contain the true-value of each checkbox. In this case, it would be:
["Team", "Questions", "Queries", "Fax"]
Here's how I would update your code:
Add a computed property to return an array of available categories:
computed: {
categories() {
const cats = this.remove_category_duplicates;
return Object.keys(cats).map(k => cats[k]);
}
}
Update select() to set cat_data based on selectAll. If selectAll is true, set cat_data to the category array computed above (thus marking all boxes checked), or else an empty array (thus unchecking all boxes):
methods: {
select() {
this.cat_data = this.selectAll ? this.categories : [];
}
}
Add a method (e.g., named "toggleSelectAll") to toggle selectAll based on whether all checkboxes are checked, keeping the Select All checkbox in sync with the state of the other checkboxes:
methods: {
toggleSelectAll(e) {
const checked = e.currentTarget.checked;
if (checked) {
this.selectAll = this.arrayContains(this.categories, this.cat_data);
} else {
this.selectAll = false;
}
}
}
Add a change-handler on each checkbox (except the Select All box) that calls toggleSelectAll defined above:
<div v-for="category in remove_category_duplicates">
<input type="checkbox" #change="toggleSelectAll">
demo
Related
I have multiple checkboxes in my angular application. When user checked and unchecked checkboxes I want to pass those true/false values into an array. It's happening from below code.
But my problem is as you can see the below console.log, it has duplicate checkbox values(index 0 and 3 have same thing) and push it to the array.
I want to know how to check duplicate objects and avoid pushing object to the array.
.ts file
layerChange(e:any){
var isChecked = e.target.checked;
var id = e.target.attributes.id.nodeValue;
const layer = {
isChecked: isChecked,
id: id,
}
this.layers.push(layer);
console.log(this.layers);
}
.html file
<input id="population" (change)="layerChange($event)" type="checkbox">
<input id="gender" (change)="layerChange($event)" type="checkbox">
<input id="householdIncome" (change)="layerChange($event)" type="checkbox">
console.log(this.layers)
**0: {isChecked: true, id: 'population'}**
1: {isChecked: true, id: 'age'}
2: {isChecked: false, id: 'population'}
**3: {isChecked: true, id: 'population'}**
You can check if an entry exists first using either :
var id = e.target.attributes.id.nodeValue;
var attr = this.layer.find(x => x.id === id);
if(!attr)
this.layers.push(layer);
or
this.layer.filter(x => x.id === id)
Edit
in your scenario is better to construct the array only one time in page load.
ngOnInit(): void {
this.layer = [{id: 'age', isChecked: false}, {id:'population',isChecked: false}]
}
and then alter the check state when user check/uncheck :-
layerChange(e:any){
var isChecked = e.target.checked;
var id = e.target.attributes.id.nodeValue;
this.layer.find(x => x.id === id).isChecked = isChecked;
console.log(this.layers);
}
You can create a string array which contains only ids and you can insert or remove elements from the array as per the selection
layerChange(e:any) {
const id = e.target.attributes.id.nodeValue;
const index = this.layers.findIndex(el => el === id)
if(index === -1) {
this.layers.push(id);
} else {
this.layers.splice(index, 1)
}
console.log(this.layers);
}
my GOD!
Kalana (and others) we need re-thinking the problem using "variables". Yes, Angular philosophy is binding variables. Variables in .ts makes the values are showed in the .html
So, some simple like declare an array of object in the .ts
layers:any[]=[{isChecked: true, id: 'population'},
{isChecked: true, id: 'age'},
{isChecked: false, id: 'population'}
]
Allow us write in .html
<ng-container *ngFor="let layer in layers">
<input type="checkbox" [(ngModel)]="layer.isChecked"
(change)="onChange()">
</ng-container>
In .ts we has a function:
onChange(){
console.log(this.layers)
}
Finally , I was able to find a solution. Thank you.
layerChange(e:any){
var isChecked = e.target.checked;
var id = e.target.attributes.id.nodeValue;
const index = this.layers.findIndex(el => el.id === id);
const layer = {
isChecked: isChecked,
id: id,
}
if(index > -1){
this.layers[index].isChecked = isChecked;
}else{
this.layers.push(layer);
}
console.log(this.layers);
}
I am trying to get the best possible solution but not getting any clue how to do it.
Task
there are 4 different multiple select drop down, and user can select any number of different values of each drop down and create a box ( limit to 7 ) through save button.
structure
> dropdown1
a1,a2,a3
> dropdown2
b1,b2,b3
> dropdown3
c1,c2,c3
> dropdown4
d1,d2,d3
Code for 1 dropdown
/* dropdown dp1 */
selecteddp1 = [];
dp1Loading = false;
dp1: any[] = [];
dp1Name = ["a1", "a2", "a3", "a4"];
selectAll() {
this.selecteddp1 = this.dp1.map(x => x.name);
}
unselectAll() {
this.selecteddp1 = [];
}
private loaddp1() {
this.dp1Loading = false;
this.dp1Name.forEach((c, i) => {
this.dp1.push({ id: i, name: c });
});
}
/* dropdown dp1 */
/* button event */
createQuery() {
this.selecteddp1.forEach(x => {
this.query.dp1.push(x);
});
}
/* button event */
on button event, saving selected dp1 value to query.
query:[] = [{
dp1: [],
dp2: [],
dp3: [],
dp4: []
}];
result (illustrated based on user selection)
<div class="box1">
<ul>
<li>dp1-a1</li>
<li>dp2-b1</li>
<li>dp2-b2</li>
<li>dp3-a1</li>
<li>dp3-c2</li>
</ul>
</div>
my approach will be wrong, kindly suggest better idea, how to save the selected value in array of objects and how to view it. TIA
Edit
I need to create box with selected value of dropdown(s). Once user click on save button.
In my view,query should be like this
query:[] = [{
dp1: [a1,a2],
dp2: [b1],
dp3: [c2],
dp4: [d3]
}],
[{
dp1: [a1,a2],
dp2: [b1],
dp3: [c2],
dp4: [d3]
}];
You can create your query array like this:
query = [{
dp1: ['a1','a2'],
dp2: ['b1'],
dp3: ['c2'],
dp4: ['d3']
}, {
dp1: ['a1','a2'],
dp2: ['b1'],
dp3: ['c2'],
dp4: ['d3']
}];
And your HTML whould be:
<div *ngFor="let dropdownGroup of query">
<select *ngFor="let dropdown of objectKeys(dropdownGroup)">
<option *ngFor="let option of dropdownGroup[dropdown]" [value]="option">{{option}}</option>
</select>
</div>
The objectKeys in the HTML is a property of the class that is equal to the object.keys:
objectKeys = Object.keys;
You can see this all together in this StackBlitz
Im trying to create a filter mechanism using this code, which works perfectly (independently):
// Report Filtering
$scope.filter = {};
$scope.getCategories = function () {
return ($rootScope.reportsData || []).map(function (report) {
return report.type;
}).filter(function (report, idx, arr) {
return arr.indexOf(report) === idx;
});
};
$scope.getPackages = function () {
return ($rootScope.reportsData || []).map(function (report) {
return report.package;
}).filter(function (report, idx, arr) {
return arr.indexOf(report) === idx;
});
};
$scope.filterByCategory = function (reportsData) {
return $scope.filter[reportsData.type] || noFilter($scope.filter);
};
$scope.filterByPackage = function (reportsData) {
return $scope.filter[reportsData.package] || noFilter($scope.filter);
};
function noFilter(filterObj) {
for (var key in filterObj) {
if (filterObj[key]) {
return false;
}
}
return true;
}
and the ng-repeat is:
ng-repeat="item in filtered=(reportsData | filter:filterByPackage)"
This works perfectly if I replace filter: with either filterByPackage or filterByCategory.
Im using this code to iterate through the keys and create checkboxes to toggle the visibility of the items:
<label ng-repeat="cat in getCategories()">
<input type="checkbox" ng-model="filter[cat]" />{{cat}}</label>
However, I would like to use these both in conjunction. If i modify my inline code on the ng-repeat to:
ng-repeat="item in filtered=(reportsData | filter:filterByPackage | filter:filterByCategory)"
then clicking on checkbox makes the entire list disappear. What is the syntax to properly combine these two filters?
If you select a category and a package you only want to display the reportData that matches with both?
The problem you are having is that you are using your "filter" object for both types of filtering and this in combination with your noFilter function that also verifies if anything is checked on the filter is causing that you need to select both a package and category exactly matching the reportData for it to be displayed (you cannot leave a filter unselected or it doesn't display any).
What you can do is initialize your filter as an object in which each criteria is a member, and utilize them as so:
$scope.filter = { packages: {}, categories: {}};
return $scope.filter.categories[reportsData.type] || noFilter($scope.filter.categories);
<label ng-repeat="cat in getCategories()">
<input type="checkbox" ng-model="filter.categories[cat]" />{{cat}}
</label>
I have rows of selects lists, when I change a list on one row, the lists for the whole table column change, is there a way each select list can have its own selected option?
I an rendering each row component use the following schema:
tableRowScheme: [
{"column":"levelId",
"title":"Level",
"type": "select",
"optionData": this.state.gradeOptions,
"afterChange": this.onLevelSelect,
"className": "col-md-1"},
{"column":"subjectId",
"title":"Subject",
"type": "select",
"optionData": this.state.subjects,
"afterChange": this.onSubjectSelect,
"className": "col-md-1"},
Then Im rendering each select list
case 'select': {
var optionsData = cellData.optionData ? cellData.optionData : [];
if(cellData.isRowInEditMode && !cellData.isNonEditable) {
return (
<div>
<TableDropdown columnName={cellData.column}
staticElements={this.props.staticElements}
optionsData={optionsData}
staticElementId={cellData.selectTypeId}
defaultValue={parseInt(this.state.rowDataStack[cellData.column])}
className="input-sm"
handleSelect={this.onDropdownChange}/>
<Input type="hidden" ref={cellData.column} standalone={true}
defaultValue={parseInt(this.state.rowDataStack[cellData.column])} />
</div>
);
Then each dropdown has this.onDropdownChange :
onDropdownChange: function(data){
var localRowDataStack = _.cloneDeep(this.state.rowDataStack);
localRowDataStack[data.filterName] = data.filterVal;
this.setState({
rowDataStack: localRowDataStack,
isOmitReRender: false
});
for (var i=0; i<this.props.rowScheme.length;i++) {
if(this.props.rowScheme[i].afterChange != undefined && this.props.rowScheme[i].column == data.filterName) {
this.props.rowScheme[i].afterChange(data.filterVal);
break;
}
}
},
I have a form where you can add x number of fields. Each field contains option select. I want to filter out the already chosen option when this option is already chosen in one or multiples field before. Each field has a remove button and the form has 1 add button.
How can I filter out the dynamic fields?
Any help,guidance is most welcome.Thanks in advance. :)
This is how my HTML looks like:
<div data-ng-repeat="choice in choices">
<select data-ng-model="choice.option"
data-ng-options="item as item.Value for item in options">
</select>
<button data-ng-click="removeChoice(choice)">Remove choice</button>
<div>
<button data-ng-show="choices.length <= 4" data-ng-click="addNewChoice()">Add Choice</button>
</div>
</div>
And my controller:
$scope.options = [
{
"Key": "0",
"Value": "Select an option"
},
{
"Key": "Option1",
"Value": "Option1"
},
{
"Key": "Option2",
"Value": "Option2"
},
{
"Key": "Option3",
"Value": "Option3"
},
{
"Key": "Option4",
"Value": "Option4"
},
{
"Key": "Option5",
"Value": "Option5"
}
];
$scope.choices = [{ id: '1' }];
$scope.addNewChoice = function () {
var newItemNo = $scope.choices.length + 1;
$scope.choices.push({ id: newItemNo, option: $scope.option, value: $scope.value });
};
$scope.removeChoice = function () {
var index = $scope.choices.indexOf(choice);
$scope.choices.splice(index, 1);
};
ok
i can give simple recommendation which will be this.
1: add variable $scope.selectedOptions = [];
this will contain list of already selected options from all select elements .
2: create function $scope.AddSelectedOption(item);
this will add the selected object when we change option from any select element because we are going to use for all selects ng-change= "AddSelectedOption(item);"
3: add checkIfSelected(item); this will check if given object value is already selected or not ..
will user in
hope you understand what it will do just check like this
$scope.checkIfSelected = function (item) {
$scope.selectedFound = $scope.selectedOptions.filter(function
(option) {
if(option.value == item.value)
{
return day;
}
});
if($scope.selectedFound.length == 0 ) { return false; } else {
return true; }
}
This will return true if give item found in the options.
if not out.. you can invite me to help again .
This is possible. I'm explaining a basic version of this requirement. See the working example here http://plnkr.co/edit/S9yZpjhY55lXsuifnUAc?p=preview
What wer are doing is maintaining another options which is the copy of the original options. Copying the options will make it to not reference existing options since objects are pass by reference in Javascript.
The main logic is in this function, which modify the options on selection:
$scope.optionSelected = function(choice) {
$scope.availableOptions = $scope.availableOptions || angular.copy($scope.options);
if (choice.option) {
var index = -1;
// See if available options has that key
angular.forEach($scope.availableOptions, function(item, i) {
if (item.Key === choice.option.Key) {
index = i;
}
});
if (index > -1) {
// And then remove it
$scope.availableOptions.splice(index, 1);
}
}
};