AngularJS ng-repeat list with buttons: Disable button after click - angularjs

I have in AngularJS a list with multiple entries and for each entry a button. When clicking the button, the application will do some stuff and after that was successful, the button should be disabled.
The interesting part in my template look like this:
<li ng-repeat="item in items">
<span>{{item}}</span>
<button ng-click="doSomeStuff(item)">Request</button>
</li>
I already tried to use the ng-if directive, but then of course every button will disappear.
Previously, I thought about a solution in raw Javascript or jQuery, because it is very easy just to modify the button by its id. But is there a solution provided by AngularJS?

Use ng-disabled as follows:
<li ng-repeat="item in items">
<span>item</span>
<button ng-click="doSomeStuff(item)" ng-disabled="item.disabled">Request</button>
</li>
Controller:
$scope.doSomeStuff = function(item) {
//do operations and finally set disabled to true for that button
item.disabled = true;
}

Related

How to run autoclick on first button in button set in ng-repeat?

I have set of buttons, I used ng-repeat. I would like to have pressed first button after load page
I thought about ng-init but I don't know how to use reference to first button..
You can use $first to return a boolean that is true if the element is the first in the array, and then put some logic in there that will check for that along the lines of
if($first){
//do something
}
or something like
ng-class="$first ? conditionA : conditionB"
if you want to conditionally set CSS
https://docs.angularjs.org/api/ng/directive/ngRepeat
You can achieve what you need with ng-init like this:
<td ng-repeat="item in items">
<a href="">
<button type="button" ng-click="onClick($index)" ng-init="$first && onClick($index)">{{item.title}}</button>
</a>
</td>
onClick function will be called only for the first button
see working demo here: demo

Angular 1.5 Binding ng-repeat created controls?

Angular 1.5
In an ng-repeat I create a button that will display a Bootstrap popup with anchor links.
How do I bind the onAction call so that it calls my $scope.onAction() function ? (onAction() is not bound to $scope.onAction().)
<div ng-repeat="item in model.Holdings track by $index" bs-popover>
<button class="popoverBtn"
data-content="<a ng-click='onAction(1)'>Buy</a>...and more"
click me to show popup
</button>
</div>
Here's my directive that turns the Bootstrap popover on:
app.directive('bsPopover', function () {
return function (scope, element, attrs) {
element.find(".popoverBtn").popover({ placement: 'auto', html: 'true' });
????COMPILE GOES HERE???////
};
});
It sounds like you want the onAction method to take an item identifier.
Perhaps something like <a ng-click='onAction(item.id)'>Buy</a> ??
From what I recall, you are in the scope of the controller that stores the data. If you have nested ng-repeats, look into $parent.
If you are looking to pass the index value of an item into your function on a click event, you need only pass it $index instead of an explicit value. For example:
<div ng-repeat="item in model.Holdings track by $index">
<button class="btn btn-primary"
data-content="<a ng-click='onAction($index)'>Buy</a>...and more">
click me to show popup
</button>
</div>
UI-Bootstrap project seems to have simple to use controls for Angular + Bootstrap.
https://angular-ui.github.io/bootstrap/
This worked

Angular.js ng-repeat unique identifier

I am using ng-repeat on a <tr> tag to populate the <td> tags with data pulled from mysql and converted into Json. This works just fine. However, one of the <td> tags that I'm using contains a button.
What I would like to do, is have each of these buttons identified somehow in the DOM, so that I can target then with specific requests.
Example: Page loads, ng-repeat repeats a button 4 times. Each of these buttons would have an ng-click attached to it. I want each of them to open and filter different information in a json file.
Am I correct in assuming that ng-repeat would simply open the same item for each button, and how would I go about making them seperate? thanks.
You can do something like this on the front-end:
<button ng-repeat="item in items track by $index" ng-click="someFunction($index)" >Something happens</button>
Then in your controller:
$scope.someFunction = function (index) {
if (index === 1):
// etc.
else...
// Or use switch, whichever works for you.
You could create the specific function on each item in the array.
<button ng-repeat="button in buttons" ng-click="button.functionName()">{{button.name}}</function>
There's $index for that. It's a very good habit to take for any of your ng-repeat. Also don't forget bind-once if your buttons UI isn't subject to modifications once the DOM has loaded.
<ul>
<li ng-repeat="page in pages">
<a ng-class="{ testClass: $index == pageNumber }" ng-click="setPageNumber($index)">{{ page }} - index is : {{$index}}</a>
</li>
</ul>
http://jsfiddle.net/bonatoc/4z1t4gsm/3/
Also you could do (using bind-once):
<button
ng-repeat="button in ::buttons track by $index"
id="button_{{$index}}"
class="{{button['css_class']}}"
...given your buttons were a JSON object as well (beware, ng-repeat likes arrays, not objects. Arrays of objects are fine):
$scope.buttons = [
0: {
'css_class': someClass,
'functionToTrigger': function(...
// ...

Override ng-hide on ng-click

On the process of trying to learn angularjs, I am creating a set of divs using ng-repeat. I have five divs in all. I am only displaying the first div using $firstdirective component.
<div class="container" ng-app="demoApp" ng-controller="demoController">
<div class="row" ng-repeat="job in jobs" ng-hide="!$first">
<div class="col-md-4">
{{job}}
</div>
<div class="col-md-4">
<button class="btn-primary btn-xs add" ng-click="showNext($event)" ng-hide="$last">Add</button>
<button class="btn-primary btn-xs delete" style="display: none;">Delete</button>
</div>
</div>
</div>
That works.
Now, each div has two buttons, Add and Delete. When I click add I want to hide the add button and delete button of the current row and open the next row. So I wrote,
$scope.showNext = function(evt) {
var elm = evt.target;
$(elm).hide();
$(elm).next().hide();
$(elm).closest("div.row").next().slideDown();
};
This is not working as ng-hide is overriding my slideDown. What is the angularjs way of doing it?
Also I would like the delete button only on the $last visible row && !first. How to find last visible row in ng-repeat?
Fiddle: https://jsfiddle.net/codeandcloud/u4penpxw/
You shouldn't manipulate the DOM with things like $(elm).hide();, you should use ng-class= to let Angular add classes that hide or show the elements. If you switch your ng-repeat to ng-repeat="job in jobs track by $index", you could write something like that in your showNext()-function:
$scope.showNext = function(index) {
$scope.currentJob = $scope.jobs[index]
}
and call it like ng-click="showNext($index) - of course you'd need to do some refactoring as well. But then you could write something like ng-class="{hidden: (job == currentJob}" to hide all buttons except in the current row.
There's a lot of good thoughts in this q&a: "Thinking in AngularJS" if I have a jQuery background?

AngularJS with ui-router ng-hide not working after initially working

I've been struggling with a ng-hide issue in combination with using ui-router. Simple app. Index.html shows some data via the "notes" route, you click on "detail" and you go to the sub route "notes.note" to view the detail just below the other records. The "detail" html has a "Save" & "Cancel" button.
Now there is an "Add New" button when you are not viewing the detail with the attribute ng-hide="HideAddNew". "HideAddNew" is a $scope variable in the controller. When I click "detail" on a row I have this ng-click="toggleAddNew()" on the link which in turn calls this
$scope.toggleAddNew= function()
{
$scope.HideAddNew=($scope.HideAddNew ? false : true);
}
That works perfectly, my detail shows and my "Add New" button has disappeared. Now on the detail when I click "Cancel" it fire off the ng-click="hideData()" which calls the function:
$scope.hideData=function()
{
$scope.toggleAddNew();
$state.go('notes');
}
And now my "Add New" has disappeared even though the variable is set to false, i.e. Don't hide. I've tried $timeout in that "hideData" function and in the "toggleAddNew" function. I've tried putting "$scope.toggleAddNew();" after the "$state.go('notes');" too. I don't want to resort to manually adding and removing classes. AngularJS ver: v1.3.15 , ui-router ver: v0.2.13 Thanx all :)
EDIT
Would the below work Tony?
<button ng-if="HideAddNew" ng-click="SelectRoute('notenew')" class="btn btn-primary">
<span class="glyphicon glyphicon-plus -glyphicon-align-left"></span>Add New</button>
Perhaps you could simplify and use ng-switch instead.
Something like this:
<ul ng-switch="expression">
<li ng-switch-when="firstThing">my first thing</li>
<li ng-switch-when="secondThing">my second thing</li>
<li ng-switch-default>default</li>
</ul>
Alternatively, maybe you could use ng-if or ng-show instead of ng-hide, eg:
<p ng-if="HideAddNew">it's here!</p>
<p ng-if="!HideAddNew">it's not here.</p>
Edit
If I understand what you're trying to achieve exactly, I would use ng-show with an ng-click:
Controller:
$scope.addNew = false;
View:
<button ng-show="!addNew" ng-click="addNew = true">Add New</button>
<button ng-show="addNew" ng-click="save()">Save</button>
<button ng-show="addNew" ng-click="addNew = false">Cancel</button>
Example

Resources