ng-repeat how to handle a button element separately - angularjs

I am using ng-repeat to populate data in a table so far so good. What i am trying to accomplish is to use a button and change it's text according to the userId (cust.id). I am trying to understand how to use a $scope inside a repeat method and modify it separately from the other elements.
On the following demo when i click to button with (userid value = 1) then i would like to change the specific button text and NOT every button in my ng-repeat
<button ng-click="perLineText(cust.id)">{{buttonText}}</button>
Live Demo
I am trying to figure out how to handle specific elements in my ng-repeat. Any help much appreciated.

You can do that by just using the this in you controller function instead of $scope.
$scope.perLineText = function(customerId){
if (customerId === 1) {
this.buttonText = 'Stop';
};
See the updated fiddle http://jsfiddle.net/u5swjwv1/
On a click callback this points to the scope of nested repeat element. If you use $scope you are actually referring to the parent scope object.
Look at this explanation too 'this' vs $scope in AngularJS controllers

A good way to handle this problem is using $index. Just pass it when calling your perLineText($index) function so you know which row you are in. Now you can simply work with the appropriate index object in your array which might my $scope.customers[index]

You can also use the ng-bind="perLineText(cust.id)" instead of the {{buttonText}} so the ng-click will toogle something and the perLineText will return Start or Stop.

Related

Angularjs + call methods by string

I have dynamically generated input elements with unique Id. I need to bind click event for each input element which will perform different action.
Is there any better way to achieve this?
Assuming you mean call methods on the controller scope dynamically, you want something like this:
$scope.callFn = function(fn) {
$scope[fn]();
}
then
<input ng-click="callFn(foo)" />
but you really need a lot more detail in your question to give a better answer.

cannot access value of dynamically generating radio button in angularjs controller using scope

I am showing radio button in html using practices is a json array
<div id="rows" ng-repeat="practice in practices">
<input type="radio" ng-model="practice.id" ng-value="practice.id">
</div>
When I tried to access value of this radio button using code mentioned below in controller, it gave me a message "undefined...."
$window.alert($scope.practice.id);
when you put something in an ng-repeat it puts the values in a child scope - so you would need to access the individual values of the practices collection by index of the collection.
like so:
$scope.practices[index].id
the other option is to also have a ng-click directive that would allow you to be notified on the user selecting the id - which you could do two ways
either:
ng-click="changedPracticeId($index)"
this would call the function defined in scope with the index, so you could access the individual item by index, like above. then the function could look something like this:
$scope.changedPracticeId = function (index) {
window.alert($scope.practices[index].id);
}
or
ng-click="changedPracticeId(practice.id)"
this would give you the id of the value so your function would look something like this:
$scope.changedPracticeId = function (id) {
window.alert(id);
}
don't see a controller per input row, so your controller is probably for ALL radio buttons.
so what you got in your scope is actually $scope.practices and not $scope.practice.
if you want to see any change, you can use
$scope.$watchCollection('practices', function (newValue) {...});

Having a set of checkboxes map to a nested array

I am working on a SPA that pulls in customer data from one $resource call, and gets some generic preference data from another $resource call.
The preference data is sent as an array, which I want to use to populate a series of checkboxes, like so:
<div ng-repeat="pref in fieldMappings.mealPrefs">
<input type="checkbox"
id="pref_{{$index}}"
ng-model="customer.mealPrefs"
ng-true-value="{{pref.name}}" />
<label class="checkbox-label">{{pref.name}}</label>
</div>
When a user clicks one or more checkboxes, I want the values represented in that array of checkboxes to be mapped to an array nested inside a customer object, like so:
.controller( 'AppCtrl', function ( $scope, titleService, AccountDataService ) {
// this is actually loaded via $resource call in real app
$scope.customer = {
"name": "Bob",
"mealPrefs":["1", "3"]
};
// this is actually loaded via $resource call in real app
$scope.fieldMappings.mealPrefs = [
{'id':"1", 'name':"Meat"},
{'id':"2", 'name':"Veggies"},
{'id':"3", 'name':"Fruit"},
{'id':"4", 'name':"None"}
];
});
I have tried setting up ng-click events to kick off functions in the controller to manually handle the logic of filling the correct part of the customer object model, and $watches to do the same. While I have had some success there, I have around 2 dozen different checkbox groups that need to be handled somehow (the actual SPA is huge), and I would love to implement this functionality in a way that is very clean and repeatable, without duplicating lots of click handlers and setting up lots of $watches on temporary arrays of values. Anyone in the community already solved this in a way that they feel is pretty 'best practice'?
I apologize if this is a repeat - I've looked at about a dozen or more SO answers around angular checkboxes, and have not found one that is pulling values from one object model, and stuffing them in another. Any help would be appreciated.
On a side-note, I'm very new to plunkr (http://plnkr.co/edit/xDjkY3i0pI010Em0Fi1L?p=preview) - I tried setting up an example to make it easier for folks answer my question, but can't get that working. If anyone wants to weigh in on that, I'll set up a second question and I'll accept that answer as well! :)
Here is a JSFiddle I put together that shows what you want to do. http://jsfiddle.net/zargyle/t7kr8/
It uses a directive, and a copy of the object to display if changes were made.
I would use a directive for the checkbox. You can set the customer.mealPrefs from the directive. In the checkbox directive's link function, bind to the "change" event and call a function that iterates over the customer's mealPrefs array and either adds or removes the id of the checkbox that is being changed.
I took your code and wrote this example: http://plnkr.co/edit/nV4fQq?p=preview

AngularJS : How to reference filtered ng-repeat items from a controller

I have some JSON data that is rendered out via the ng-repeat directive, and the results are then filtered via some checkboxes/drop-downs, and some custom filter functions in my controller.
I now want to add a function to my controller that is triggered by an 'ng-change' on some of the checkboxes, that can reference the current list of items in my 'ng-repeat'. I realise I can reference these values from a custom filter, for example $scope.filterProvider = function(item), but this function is then called for each and every item in the ng-repeat, which isn't what I want - I want the function to just be called each time a checkbox is checked/unchecked, and I need that function to be able to reference the items in my ng-repeat...does that make sense to anyone?! And if so, does anyone know how I can do that?
Thanks :-)
Say you have ng-repeat="item in items", then you may use something like ng-click=thisAmazingFct(item) that will pass the current item while calling thisAmazingFct.
If you prefer using the index of the item in the items array, use something like ng-click=thisAmazingFctByIndex($index) where $index is automatically set to the current item index by angular with the ng-repeat directive.

AngularJS: Deleting from scope without hardociding

I have an array of items bound to <li> elements in a <ul> with AngularJS. I want to be able to click "remove item" next to each of them and have the item removed.
This answer on StackOverflow allows us to do exactly that, but because the name of the array which the elements are being deleted from is hardcoded it is not usable across lists.
You can see an example here on JSfiddle set up, if you try clicking "remove" next to a Game, then the student is removed, not the game.
Passing this back from the button gives me access to the Angular $scope at that point, but I don't know how to cleanly remove that item from the parent array.
I could have the button defined with ng-click="remove('games',this)" and have the function look like this:
$scope.remove = function (arrayName, scope) {
scope.$parent[arrayName].splice(scope.$index,1);
}
(Like this JSFiddle) but naming the parent array while I'm inside it seems like a very good way to break functionality when I edit my code in a year.
Any ideas?
I did not get why you were trying to pass this .. You almost never need to deal with this in angular. ( And I think that is one of its strengths! ).
Here is a fiddle that solves the problem in a slightly different way.
http://jsfiddle.net/WJ226/5/
The controller is now simplified to
function VariousThingsCtrl($scope) {
$scope.students = students;
$scope.games = games;
$scope.remove = function (arrayName,$index) {
$scope[arrayName].splice($index,1);
}
}
Instead of passing the whole scope, why not just pass the $index ? Since you are already in the scope where the arrays are located, it should be pretty easy from then.

Resources