Checkbox Unchecking after AngularJS sorting - javascript

I currently have a table listing jobs. Each job has a checkbox.
<form name="jobsSampleSelectForm" id="jobs-sample-select-form">
<div jobs="data">
<div ng-form="jobsSampleSelectForm">
<table ng-table="tableParams" class="table" show-filter="true">
<tr ng-repeat="job in $data" class="table-highlight" ng-class="{deactivated: job.is_active == 'No'}">
<td data-title="'Sample'"><input type="checkbox" ng-model="job.selected"></td>
<td data-title="'QC ID'" sortable="'id'">{{job.id}}</td>
<td data-title="'Date Submitted'" sortable="'dateJob'">{{job.dateJob}}</td>
</tr>
</table>
</div></div>
<button type="submit" class="btn btn-primary-red" ng-click="sampleJobs()" ng-disabled="(jobs | filter: job.selected != true).length <= 0">Sample Jobs</button>
</form>
This allows the user to select the jobs they want. However, when the user sorts a column the checkbox will uncheck itself. This seems to be a common issue, so from the advice from this SO question I added a selected attribute to each job in my controller.
jobsService.getJobsByStatuses(["pre_sampling", "sampling", "setup"])
.success(function(data){
data.forEach(function(job){ job.selected = false; });
$scope.jobs = data;
var filteredData = params.filter() ? $filter('filter')(data, params.filter()) : data;
var orderedData = params.sorting() ? $filter('orderBy')(filteredData, params.orderBy()) : data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
params.total(orderedData.length);
})
This did not seem to cause a difference. What am I missing?
I created a Fiddle to show the basic idea. When the user selects checkboxes, then sorts, the checkboxes become unchecked.

just change
<td data-title="'Sample'"><input type="checkbox" ng-model="job.selected"></td>
to
<td data-title="'Sample'"><input type="checkbox" ng-model="user.selected"></td>
If you want to persist the row selection then you should bind the checkbox to user.selected instead of binding to job.selected.
If you use user.selected for ng-model each row will have its own user object with selected property binded to checkbox so that you will get the selection even after the sorting
see the updated fiddle

<input type="checkbox" ng-model="user.selected">
Working fiddle http://jsfiddle.net/PQvQ2/83/
You are not capturing the checkbox value anywhere. In the user object, you already have "selected" to capture the selection. Using the same will store the selection. If you are using a different object "job", you will capture the index of selection but it will not be mapped to the correct value. Since, "job" object only store the checkbox selected, nothing more.

The issue was that I was calling getData every time a filter was applied. This was setting my selected attribute on each job to false. To fix this issue, I moved my code to get the data outside of the getData function.

Related

keeping the "checked" value to an input checkbox after search using ng-repeat | Angularjs

I have to let the user select items to submit them later on, but my problem occur when selecting multiple items and then search for another items to select them, the previous selected items rested to default values unchecked.
how to keep the checked value to the selected items after calling again getAllItems function? because what happens is that the ng-repeat clear the value of the previous selected items.
My view:
<div id="dialog-items">
// the search box
<input ng-change="getAllItemNames(searchValMultiItems)" ng-model="searchValMultiItems" type="text"/>
<table>
<th>Designation</th>
<th>Colisage</th>
<th>Code</th>
//the mark() function is to set checked value to selected input and store the item in an array
<tr ng-repeat="d in allDesignation" ng-click="markItem(d.itemName); ischeck=true;">
<td ><input type="checkbox" ng-checked="ischeck" /> {{d.itemName}}</td>
<td>{{d.item_colisage}}</td>
<td>{{d.code}}</td>
</tr>
</table>
</div>
JS:
//calling this function to search for an item
$scope.getAllItemNames=function(searchValMultiItems){
var searchItems=searchValMultiItems;
var url="../php/mainPageFacture.php";
var data = {"function":"getAllItemNames","searchValMultiItems":searchItems};
var options={
type : "get",
url : url,
data: data,
dataType: 'json',
async : false,
cache : false,
success : function(response,status) {
$scope.allDesignation=response;
$scope.safeApply(function() {});
},
error:function(request,response,error){
alert("Error");
}
};
$.ajax(options);
}
/*this is responsible to set checked value to true when
item is selected and store all selected item in an array*/
$scope.markItem=function(itemName){
if( $.inArray(itemNameWithCode, multiSelectItem_names) !== -1 ) {
alert("This Item is already added to this Invoice");
}else{
multiSelectItem_names.push(itemNameWithCode);
}
}
I store all selected items in an array and even after search the array keep the value, but problem is only whith the checked mark, i'll attach a photo for more clarification
Make the checked property part of the items in the list.
<tr ng-repeat="d in allDesignation" ng-click="markItem(d.itemName); d.ischeck=!d.ischeck;">
<td ><input type="checkbox" ng-checked="d.ischeck" /> {{d.itemName}}</td>
<td>{{d.item_colisage}}</td>
<td>{{d.code}}</td>
</tr>
This requires some changes in your implementation.
An option would be to store the list items in $scope.
$http.get('dataurl')
.then(function(response) {
$scope.items = response.data;
});
You can use a filter to filter the items in the ng-repeat.
<tr ng-repeat="d in items | filter:{ property: filterText }">...</tr>
See here ng-repeat :filter by single field

ng-change event firing only once inside ng-repeat

Here in my form, I am using two radio buttons and would like to check the selected values. But this does not work as expected. I would like to determine the individual radio selection value and display Big/Small in the Result column
<div ng-controller="CityCtrl">
<table>
<tr>
<th>Name</th>
<th>Big</th>
<th>Small</th>
<th>Result</th>
</tr>
<tr ng-repeat="city in cities">
<td>{{ city.name }}</td>
<td>
<input type="radio" name="{{city.name}}-{{$index}}" ng-model="big" value="big_value" ng-change="check(city.name, big)">
</td>
<td>
<input type="radio" name="{{city.name}}-{{$index}}" ng-model="small" value="small_value" ng-change="check(city.name, small)">
</td>
<td>***</td>
</tr>
</table>
</div>
Controller:
var myApp = angular.module('cityApp', []);
function CityCtrl($scope) {
$scope.big = '';
$scope.small = '';
$scope.cities = [{
id: 1,
name: 'Tokyo'
}, {
id: 2,
name: 'Guangzhou'
}, {
id: 3,
name: 'Seoul'
}];
$scope.check = function(city, value) {
console.log("City->" + city + " ::: Value->" + value);
};
}
From other answers I did infer a few things:
Understand Prototypical Inheritance in JS ?!
ng-repeat creates child scope that affects these radios inside ng-repeat
use $parent on ng-modal in the radio
I did played around, but couldn't make this work, I guess I am making some obvious mistake here.
Here is the fiddle:
http://jsfiddle.net/mw2us37h/
NOTE:
I am not using ng-value but passing a hardcoded value.
Changing to ng-click doesnt work either
Flagged this as a duplicate, but it seems like the solution is to use ng-click instead of ng-change when working with radio buttons in angularjs.
Here is an edit of your fiddle that works: http://jsfiddle.net/mw2us37h/1/
I'm not sure I understand what your trying. I think you like to display the radio button value in the result column and/or have a function on click where the value is passed.
Display the radio button value in result column
I would change the ngModel value so it binds to something city specific. So change:
<input type="radio" name="{{city.name}}-{{$index}}" ng-model="big" value="big_value">
to:
<input type="radio" name="{{city.name}}-{{$index}}" ng-model="city.size" value="big_value">
and
<input type="radio" name="{{city.name}}-{{$index}}" ng-model="small" value="small_value">
to
<input type="radio" name="{{city.name}}-{{$index}}" ng-model="city.size" value="small_value">
So the model points to the same variable city.size, this is where the selected value will be saved. Then change *** in the result column to city.size
See changes fiddle: http://jsfiddle.net/u2kxuyr7/
Get value on ngClick
Use ngChange as you allready do I would do it a bit different for simplicity. Change:
ng-change="check(city.name, whatEverValue)"
to:
ng-change="check(city)"
and the check function would look like:
$scope.check = function(city) {
console.log("City->" + city.name + " ::: Value->" + city.size);
};
See fiddle: http://jsfiddle.net/Lmszxj8s/
Then ngChange is fired on each change.

How pick up checkbox result in post method angularjs

I have a table that sets out a list of rules. When the checkboxes are clicked, I need them to take this "true" value and post to an API endpoint. This has been set up, but what I am getting back is that "associated_rule" is undefined.
I have tried setting $scope.associated_rule.selected = true; in my controller, but this still doesn't define the variable and throws up the same error in the console.
Here is my HTML form:
<form name="rules_form" method="post" ng-submit="attach()">
<table class="table table-striped table-hover" ng-model="associated_rules">
<thead>
<th>Rule Types:</th>
<th>Description:</th>
<th>Start Time:</th>
<th>End Time:</th>
<th>Apply Rule to Vehicle:</th>
</thead>
<tr ng-repeat="associated_rule in associated_rules">
<td>#{{ associated_rule.resource_ids.accounts }}</td>
<td>#{{ associated_rule.description }}</td>
<td>#{{ associated_rule.start_time }}</td>
<td>#{{ associated_rule.end_time }}</td>
<td><input type="checkbox" ng-model="associated_rule.selected" aria-label="rule"></td>
</tr>
</table>
<button class="btn btn-primary" ng-click="attach()">Attach</button>
</form>
My Controller event:
$scope.attach = function () {
$scope.associated_rule.selected = true;
var i;
for (i = 0; i < $scope.associated_rule.selected.length; i++) {
//need to create a loop where the true value is picked up and then I can send the data using a POST method. But I'm stuck on this.
}
console.log(the result of the event);
};
For now, I just want the results to console.log, so I can see that the event is creating the loop and displaying the results. After that, I should be OK.
Any help would be much appreciated.
I have fixed this by defining the $scope.rule as an empty array and setting the $scope.rule.selected to "false" by default.
Great! step one! But the checkboxes are ALL selecting when you click A checkbox - think this may be the ng-repeat causing me a pain in the backside.
$scope.rule = [];
$scope.rule.selected = false;
So, how do I ensure that only the checkboxes set that I select and not all at once?
Fixed this too; as the above was just making the entire array selected; as i wasn't drilling down into the array. This did it:
ng-model="rules.selected[associated_rule.id]"
by modelling the a rule within that defined array, it shows up when testing. Brill. :)
By mistake you are changing the value of your check box on clicking the button:
$scope.associated_rule.selected = true;
This will give the current value, selected or not selected
$log.log($scope.associated_rule.selected);

Parsing JSON result to object by using checkbox

I have loaded a JSON list into a table and I would like to parse 1 JSON result or multiple results into an object, so I can send it to the server.
My table looks like this so far:
HTML
<tr ng-repeat="t in student">
<td ng-model="herkanserNaam">{{ t.Name }}</td>
<td>{{ t.City }}</td>
<td>
<div class="checkbox" ng-click="laatzien(herkanserNaam, herkanserCheck)" ng-model="herkanserCheck">
<label>
<input type="checkbox">
</label>
</div>
</td>
</tr>
Controller
$scope.laatzien = function(name, active) {
var herkanser = [{
"name" : name,
"active" : false
}];
console.log(herkanser);
}
How would I be able to check one or multiple results and save the data(t.Name) into an object by using a checkbox? So far the function laatzien() is returning the empty values defined in herkanser.
The reason your laatzien method is failing is due to how you are using your directives. Let's work with the example you provided to get your laatzien method to fire.
HTML
<tr ng-repeat="student in students">
<td>{{ student.Name }}</td>
<td>{{ student.City }}</td>
<td>van</td>
<td>Huis</td>
<td>j.huis#student.han.nl</td>
<td>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="student.isActive" ng-change="laatzien(student)">
</label>
</div>
</td>
</tr>
Javascript
$scope.laatzien = function (student) {
var herkanser = [{
"name": student.name,
"active": student.isActive
}];
console.log(herkanser);
}
I have made some opinionated changes in your example for readability purposes, others were needed to get the directives to fire as expected. Below are the changes to your snippets.
Renamed the student array to students. This will require a change in your controller from $scope.student to $scope.students.
Renamed the t object to student.
Removed the ng-click directive from your div.
Added an ng-change directive on your checkbox. Now when you click the checkbox your laatzien method should fire.
Added an isActive property to your student. Inside of your laatzien method, you may now check the state of the checkbox. If the checkbox is checked, student.isActive = true. If the checkbox is not checked, student.isActive = false.
From your code, you seem to want to build the "list of checked students" and send that to the server. In other words, what you want, is to allow the user to check on multiple students and at the end collect everything that was checked and send it over to the server.
If that's the case then your strategy to put an ng-click over the checkbox is wrong.
What you need is to bind your checkbox to your $scope model. Such as this:
<input type="checkbox" ng-model="t.isChecked" ng-true-value="true" ng-false-value="false'">
When the user checks the checkbox for a student. Your model will automatically be updated.
To collect the data to send over the server you need to put an ng-click on a submit button. In the event handler, simply loop through every student in your $scope "students" model and only save the ones that have isChecked property to true to be sent over to the server.
Hope this helps!
You could make a function to push thet item into an obj like so...
$scope.students = [
{
"name":"John",
"city":"Boston"
},
{
"name":"Amy",
"city":"Dallas"
}
]
$scope.activeObj = [];
$scope.laatzien = function(obj) {
if($.inArray(obj, $scope.activeObj) == -1) {
$scope.activeObj.push(obj);
} else {
var index = $scope.activeObj.indexOf(obj);
$scope.activeObj.splice(index, 1);
}
}
http://jsfiddle.net/5fcnazb2/

angularJs - Is it possible for 2 different models of different structures to sync or share states?

I have a list of checkboxes and values I"m loading from a list which comes back from the database.
Controller
listA = ['item1','item2'...'itemn']; //Master list of items
$scope.selectedItems = ["item1",... "item5"]; //selected items
$scope.attributesModel = [ //new model based on selected items
{"index":5,"attribute":"item1"},
{"index":10, "attribute":"item2"},
{"index":13, "attribute":"item3"},
{"index":21, "attribute":"item4"},
{"index":24, "attribute":"item5"}
];
View part 1
<td>
<div class="checkbox checkbox-notext">
<input checklist-model="selectedItems" checklist-value="key" type="checkbox" id="{{key}}" ng-disabled="exceededLimit && !checked" />
</div>
</td>
<td>
<label for="{{key}}">{{key}}{{$index}}</label>
</td>
view part 2
<div ng-repeat="(index, row) in attributesModel" >
<div class="margin10">
<div>Index<input ng-model="row.index" value="row.index" type="number" class="indexInputs"></input>{{row.attribute}}</div>
</div>
</div>
Now I would like to sync $scope.selectedItems and $scope.attributesModel. When a checkbox is deselected, both selectedItems and attributesModel models remove that item, and vice versa. So every time someone checks a new checkbox they are presented a attributesModel with an empty text field to type the index value.
catch The index key is null initially for every newly selected item that is added to attributesModel. The user must enter a new index # once the new item is created.
I've tried using watch but the problem I run into is when a new item is selected, I don't have access to the item itself. I only have access to the list without any idea whether the new item is X or if the item removed is Y in order to push/delete the right item.
So this might be a watch solution that I'm missing.
Let me know if I can clarify anything.
I am not sure what the problem is, but you could use ngChange on the checkboxes:
<input type="checkbox" ... ng-change="..." />
I asdume you have a checklist directive or something, so should do something there, but (since you don't share it with us) I can't tell what exactly :)
UPDATE:
Since the checklist directive is an external dependency, you could handle the ng-chage in your code:
<input type="checkbox" ... ng-change="changed(key)" />
/* In the controller: */
...
$scope.changed = function (key) {
if ($scope.selectedItems.indexOf(key) === -1) {
// The checkbox for `key` was unchecked...
} else {
// The checkbox for `key` was checked...
}
};

Categories

Resources