Click Table Row to Trigger a Checkbox Click in Angularjs - angularjs

I have a simple table in an Angularjs app that contains a checkbox in each row.
<table>
<tr ng-repeat="obj in objList">
<td>
<input type="checkbox" ng-model="selectedObjs" value="{{obj}}"
ng-checked="obj.selected"
ng-click="toggleObjSelection(obj.description)">
{{obj.description}}
</input>
</td>
</tr>
</table>
Is there a way in Angularjs to allow the user to click any where within the row to trigger the checkbox click once?
If the user clicks in the checkbox, we don't want to trigger the click so that it appears that the checkbox click was triggered twice.
This article (http://www.learningjquery.com/2008/12/quick-tip-click-table-row-to-trigger-a-checkbox-click/) describes how to do this in jQuery, but is there a way to do this using Angularjs style?

You're pretty close you just need to stopPropagation on the $event object:
<table ng-controller="ctrl">
<tr ng-click="rowClicked(obj)" ng-repeat="obj in objList">
<td>
<input type="checkbox" ng-model="selectedObjs" value="{{obj}}"
ng-checked="obj.selected"
ng-click="toggleObjSelection($event, obj.description)">
{{obj.description}}
</input>
</td>
</tr>
</table>
And the JS:
angular.module('myApp', [])
.controller('ctrl', function($scope) {
$scope.objList = [{
description: 'a'
},{
description: 'b'
},{
description: 'c'
},{
description: 'd'
}];
$scope.toggleObjSelection = function($event, description) {
$event.stopPropagation();
console.log('checkbox clicked');
}
$scope.rowClicked = function(obj) {
console.log('row clicked');
obj.selected = !obj.selected;
};
});
http://jsfiddle.net/Ljwv0toh/7/
Related question: AngularJS ng-click stopPropagation

Related

How to send data from a table generated with a form inside a ng-repeat

I have a table generated with a ng-repeat directive.
Each cell can be editable and each row has a submit button.
The submit button must send only the data of the affected row to the controller instead of sending the complete table. Then the controller will send it to a database. So if my table is huge and has a lot of rows, I prefer to just send one row to the database instead of the complete table.
Most of the time I use <form name="myForm" ng-submit="sendMyData()"> to send data from the view to the controller but in this case I have multiple forms (one per each row).
My problem is that I have no idea how to identify each row generated by the ng-repeat.
I am using AngularJS Material.
You don't need forms to do this. I'll demonstrate how to achieve this using sample data:
Controller:
app.controller("MyController", function($scope) {
$scope.persons = [
{ id: 1, name: "Bob" },
{ id: 2, name: "Alice" }
];
$scope.submitPerson = function(person) {
// do something to person - send to backend etc...
};
});
View:
<div ng-controller="MyController">
<table>
<tr ng-repeat="person in persons">
<td>{{person.name}}</td>
<td><button ng-click="submitPerson(person)">Submit</button></td>
</tr>
</table>
</div>
By clicking the submit button within each row - the individual person object will be passed to the submitPerson function in your controller where you can send it to the backend or do anything else.
You can try something like below just to submit one row at a time and also change in any number of rows and tick box which rows to be updated at once by clicking Submit ALL button.
var app = angular.module('app',[]);
app.controller('noduesaccountsmodalcontroller',function($scope){
$scope.nodueaccountassets = [{'name':'x'},{'name':'a'},
{'name':'b'},{'name':'c'},{'name':'d'}];
$scope.init= function(){
};
$scope.selectedItems =[];
$scope.rowSubmit = function(row){
$scope.submittedRow = row;
};
$scope.submit = function(acc){
angular.forEach($scope.nodueaccountassets,function(emp){
if(emp.selected){
$scope.selectedItems.push(emp.name);
}
});
};
});
<script data-require="jquery#*" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<script data-require="angularjs#1.5.8" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
<body ng-app="app" ng-controller="noduesaccountsmodalcontroller" ng-init="init()">
<table class="table">
<thead>
<tr>
<th>item</th>
<th>received</th>
</tr>
</thead>
<tbody ng-repeat="emp in nodueaccountassets track by $index">
<tr>
<td><input type="text" ng-model="emp.name"/></td>
<td>
<input type="checkbox" ng-model="emp.selected" value="{{emp.name}}" />
</td>
<td> <button type="button" value="submit" ng-click="rowSubmit(emp)">Submit</button></td>
</tr>
</tbody>
</table>
{{selectedItems}}
Submitted row --- {{submittedRow}}
<button type="button" ng-click="submit()" value="submit">Submit ALL</button>
</body>

Disable or enable button per item in angularjs

I have a list of participants. Each participant have dial and mute buttons. I want to disable mute button at first and enable it only after dial button is clicked. Currently, if I click on dial button of say Participant 1, all the mute buttons of other participants enables. But I want to enable mute button of only Participant 1.
HTML:
<body ng-controller="MainCtrl">
<table>
<tr ng-model="participant.partName" ng-repeat="participant in participants">
<td>{{participant.partName}}</td>
<td>
<button ng-click="mutePart(participant.partName);">Mute</button>
</td>
<td>
<button ng-click="dial(participant.partName)">Dial</button>
</td>
</tr>
</table>
</body>
JS:
$scope.participants = [
{
partName: 'abc',
partId: '123'
},
{
partName: 'def',
partId: '1234'
},
{
partName: 'xyz',
partId: '12345'
},
]
$scope.mutePart = function(item){
}
$scope.dial = function(item){
}
<body ng-controller="MainCtrl">
<table>
<tr ng-model="participant.partName" ng-repeat="participant in participants">
<td>{{participant.partName}}</td>
<td>
<button ng-disabled="!callSessions[$index]" ng-click="mutePart(participant.partName);">Mute</button>
</td>
<td>
<button ng-click="dial(participant.partName, $index)">Dial</button>
</td>
</tr>
</table>
</body>
controller:
$scope.callSessions= {};
$scope.dial = function(name, index){
$scope.callSessions[index] = true;
}
Since ngRepeat will create its own child scope per each iterated item, you can set a variable in the view that will be limited to that scope:
<tr ng-repeat="participant in participants">
<td>{{participant.partName}}</td>
<td>
<button ng-disabled="!isDialing" ng-click="mutePart(participant.partName);">Mute</button>
</td>
<td>
<button ng-click="isDialing = true; dial(participant.partName)">Dial</button>
</td>
</tr>
Also, the ngModel on the tr is useless. Remove it. If you need more control over the variable (like to re-enable it when it's done calling, you should add a property to your model and toggle it):
{
partName: 'abc',
partId: '123',
isDialing: false //Added property, now toggle this
}

What triggers a function call in other column when ngmodel changes in first column?

Consider the snippet:
JS
var mod = angular.module('module', []);
mod.controller('controller', function($scope) {
$scope.items = [{
id: 1,
label: 'aLabel',
subItem: {
name: 'aSubItem'
}
}, {
id: 2,
label: 'bLabel',
subItem: {
name: 'bSubItem'
}
}]
$scope.getValue = function(ngmodel) {
// some code goes here...
}
});
HTML
<body ng-controller='controller'>
<div>
<table>
<tr ng-repeat='count in counter'> // 5 times
<td>
<select ng-options="item.id as item.label for item in items"
ng-model="selected[$index]">
</select>
</td>
<td>
{{getValue(1)}}
</td>
<td>
</td>
</tr>
</table>
</div>
</body>
As soon as I select some value from the dropdown (select tag) in the first column, I notice that the function in the second column is triggered? What is the reason for this? What exactly is happening behind the scenes?
The reason is you are doing it inside ng-repeat
<tr ng-repeat = 'count in counter'>
You need to pass the object on the controller, in order to do some action on the same.
{{getValue(obj)}}

Select All directive in AngularJS

I am using Checklist model directive with my App. I have issue, if -
I click select all button though it write up the array but its not
selecting checkbox. Same issue with Uncheck All though it empty the
model but it doesn't uncheck checkboxes.
If I select 2 or 3 randomly checkbox and click Select All Button it doesn't select All check-boxes.
Though its writing values to pushArray. But issues are checking and unchecking checkboxes.
$scope.items = [{id:1, name:"abc"},{id:2, name:"def"},{id:3, name:"ghi"}];
$scope.pushArray = [];
<table>
<tr ng-repeat="e in items">
<td class="text-right">
{{e.id}}
<input type="checkbox" checklist-change="imChanged()" checklist-model="pushArray" checklist-value="e.id" >
</td>
</tr>
</table>
I think you are pushing the complete list of object which is wrong. You just need to map the list and pass the id to the $scope
Edit: Works fine when you use $scope.pushArray as an object instead of array.
Working Plnkr
HTML
<body ng-controller="selection">
<table>
<tr ng-repeat="e in items">
<td>
<input type="checkbox" checklist-model="pushArray.ids" checklist-value="e.id"> {{e.name}}
</td>
</tr>
</table>
{{pushArray.ids | json}}
<br />
<button ng-click="select_all();">Select All</button>
<button ng-click="unselect_all();">Unselect All</button>
</body>
JS
var app = angular.module('app', ["checklist-model"]);
app.controller('selection', ['$scope', function($scope) {
$scope.items = [{
id: 1,
name: "abc"
}, {
id: 2,
name: "def"
}, {
id: 3,
name: "ghi"
}];
$scope.pushArray = { ids: []}; // Works fine when using it as an object
//$scope.pushArray = [];
$scope.select_all = function() {
$scope.pushArray.ids = $scope.items.map(function(item) { return item.id; });
};
$scope.unselect_all = function() {
$scope.pushArray.ids = [];
};
}]);
Hope it works for you!
I updated the examples on checklist-model and fix this issue. Check them out http://vitalets.github.io/checklist-model/

How to watch ng-model included in ng-repeat?

This is my html code:
<table>
<tr ng-repeat="park in parkOptions.parks">
<td>
<label for="{{park.park_id}}">
<input id="{{park.park_id}}" type="radio" name="connection" ng-model="$parent.currentPark" value="{{park.park_id}}" ng-click="selectValue('park',park)"/>{{park.park_name}}
</label>
</td>
</tr>
</table>
How can i watch the changes in my model( I mean i want to see in $watch another park when i click radio button)
I've got a working version to help you - Fiddle.
HTML
<div ng-app ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl">
<table>
<tr ng-repeat="park in parkOptions.parks">
<td>
<label for="{{park.park_id}}">
<input id="{{park.park_id}}" type="radio" name="connection" ng-model="parkOptions.currentPark" value="{{park.park_id}}" ng-click="selectValue(park)"/> {{park.park_name}}
</label>
</td>
</tr>
</table>
</div>
</div>
JS
function ParentCtrl($scope) {
}
function ChildCtrl($scope) {
$scope.parkOptions = {};
$scope.parkOptions.parks = [
{park_id: '01', park_name: 'England Park'},
{park_id: '02', park_name: 'France Park'}
];
$scope.$watch('parkOptions.currentPark', function(newValue) {
if (newValue != undefined) {
console.log(newValue);
}
});
}
This may not be exactly what you want (as I see $parent in your code) but we can come to the right solution with any further information from you.
I don't use $parent and prefer sending and receiving events.

Resources