6

So I have a button called "show more" that will increase the number of items in a list once it reaches the maximum number of list I want to change to a button called "show less" which brings the list back to its default value.

I use an ng-if to determine which button to be shown and ng-click to determine the action. When using them together the ng-click stops working and nothing happens when I click.

here is the html I have written in jade, feedLimit is the number of items showing in the list.

button.btn.btn-primary.btn-block.btn-sm.btn-outline(type='button')(ng-if= "feedLimit < notifications.all.length", ng-click="feedLimit = feedLimit + 4")
  span(translate) Show More
button.btn.btn-primary.btn-block.btn-sm.btn-outline(type='button')(ng-if= "feedLimit >= notifications.all.length", ng-click="feedLimit = 4")
  span(translate) Show Less

I've tried using ng-show and ng-hide and they work fine but it is better to use ng-if, there is no animation and it is faster.

Here is the show more button's html output

<button type="button" ng-if="feedLimit < notifications.all.length" ng-click="feedLimit = feedLimit + 4" class="btn btn-primary btn-block btn-sm btn-outline ng-scope" style=""><span class="ng-scope">Show More</span></button>
grasshopper
  • 918
  • 4
  • 13
  • 29
  • I noticed you have a space after your `=` on your `ng-if`. Maybe Jade is mis-interpreting the ng-if attribute? – James M. Lay Sep 04 '14 at 04:02
  • 1
    Angular 1.2 doesn't appear to have any problems with having ng-if and ng-click on the same element. http://jsfiddle.net/bgcgfnqr/1/ – James M. Lay Sep 04 '14 at 04:05
  • tried deleting the space no dice, also @JamesM.Lay you used a function which maybe making a difference. – grasshopper Sep 04 '14 at 04:36
  • Oh yeah, I looked right over that. It definitely appears to be influencing the problem. [fiddle here](http://jsfiddle.net/bgcgfnqr/5/) – James M. Lay Sep 04 '14 at 04:45
  • Looks like you found a bug! [evidence here](http://jsfiddle.net/bgcgfnqr/7/). Maybe consider submitting a bug on the [angular issue tracker](https://github.com/angular/angular.js/issues) – James M. Lay Sep 04 '14 at 04:53
  • do you think ng-switch would just as good of an idea as ng-if, or should i just make my own function? – grasshopper Sep 04 '14 at 05:01
  • Nope, doesn't appear to make a difference. [plunkr here](http://plnkr.co/edit/B3zmxNUbWRLMsxSqPCf0?p=preview). I would try instead either avoiding inline functions for ng-click or wrapping your buttons in a that holds the ng-if directive. – James M. Lay Sep 04 '14 at 05:08
  • Possible duplicate of [AngularJS: ng-if not working in combination with ng-click?](http://stackoverflow.com/questions/19812116/angularjs-ng-if-not-working-in-combination-with-ng-click) – Motin Feb 16 '17 at 09:29

1 Answers1

8

I think your running into a common issue with angularjs and child scope inheritance.

You are data-binding to a primitive value and ng-if is creating a child scope. When your ng-click directive changes the value of 'feedLimit', you are actually creating a new 'feedLimit' property on the child scope but the ng-if directive is bound to the 'feedLimit' of the parent scope.

The solution is to avoid binding to a primitive value. Instead make sure you use dot-notation by binding to an object.

Instead of

<button ng-if="feedLimit < notifications.all.length" ng-click="feedLimit = feedLimit + 4">

try something like

<button ng-if="someObj.feedLimit < notifications.all.length" ng-click="someObj.feedLimit = someObj.feedLimit + 4">

Here is a more detailed explanation of whats going on.

https://github.com/angular/angular.js/wiki/Understanding-Scopes

Scope inheritance is normally straightforward, and you often don't even need to know it is happening... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope. It doesn't work the way most people expect it should work. What happens is that the child scope gets its own property that hides/shadows the parent property of the same name. This is not something AngularJS is doing – this is how JavaScript prototypal inheritance works. New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view and ng-include all create new child scopes, so the problem often shows up when these directives are involved. (See this example for a quick illustration of the problem.)

This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models

jcruz
  • 718
  • 6
  • 13