ng-click odd behavior when using "var = !var" - angularjs

<accordion class="nested-accordion">
<accordion-group ng-repeat="item in menu" is-open="item.opened" ng-if="item.children == true && item.grandchild == true">
<accordion-heading id="inner-accordion">
---- PROBLEM HERE ----
<div ng-click="item.opened = !item.opened" class="toggle-caret">
<span class="glyphicon glyphicon-play" ng-class="{true: 'caret-open', false:'caret-closed'}[item.opened]"></span>
</div>
<button class="btn-link filter-option" ng-class="{true:'option-checked', false:''}[item.checked]" ng-click="test(item, $event); $event.stopPropagation()">{{item.name}}</button>
</accordion-heading>
<div>
<!-- some stuff here -->
</div>
</accordion-group>
</accordion>
I am having an issue with the line I singled out in the code above. The ng-click is not toggling the item.opened from true to false. However, if I change the syntax from:
ng-click="item.opened = !item.opened"
to:
ng-click="item.opened != item.opened"
the accordion works as expected. This is not what I want though.
Further more this is the only part out of the accordion that is experiencing this issue. Can anyone explain why this is giving me a hard time?

Related

How to bind a part of a variable already binded

I have a loop ng-repeat that displays sevral icons.
<div class="box">
<div class="box-body">
<div class="row" >
<div class="col-sm-6" style="margin-bottom: 5px;" ng-repeat="record in newlayout.display" align="center">
<a class="btn btn-app" ng-href="#newlayout/{{newlayout.url}}{{newlayout.itemValue}}" >
<span class="badge bg-yellow" style="font-size:22px;">{{record.numberOfSamples}}</span>
<i class="fa fa-{{newlayout.labStyle}}"></i> {{record.lab}}
</a>
</div>
</div>
</div>
</div>
My issue is that the second part of the binded variable itemValue should be dynamic
In my Js, I have this
newLayout.url = 'sublabs/?labName=';
newLayout.itemValue = 'record.lab';
The URL is dynamic.
When I click on the first displayed Icon, the url should look like this :
But it didn't work as I had a compilation error..
Does someone have an idea how to fix this:
http://localhost:8181/#/newlayout/sublabs?labName=PIA/C1 - Shiftlabo
Where the record value "PIA/C1 - Shiftlabo" change.
So basically here if I change
<a class="btn btn-app" ng-href="#newlayout/{{newlayout.url}}{{newlayout.itemValue}}" >
{{newlayout.itemValue}} by {{record.lab}} it would work..but the {{record.**lab**}} should be dynamic as it will have another value when I click on the icon. It will change to {{record.subLab}}
Thanks
Use property acccessor bracket notation inside the binding:
<div>{{record[labOrSublab]}}</div>
JS
var isSublab = false;
$scope.labOrSublab = "lab";
$scope.clickHandler = function() {
isSublab = !isSublab;
$scope.labOrSublab = isSublab ? 'subLab' : 'lab';
};

Angularjs: how change icon when item is clicked

I know that this question has already some answers/solutions but none of them works for me most probably because this is the first time when I'm trying to implement something using Angularjs.
I have a div (title) that expands some info when it's clicked and I want to change the icon inside of it when that info is visible...
This is my code:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right"></i>
</div>
And this is what I tried to do, but not working because the div will not show the expanded info anymore:
<div class="title" ng-click="view_variables(request) = !view_variables(request)">
<i ng-class="{'glyphicon glyphicon-chevron-right':!view_variables(request), 'glyphicon glyphicon-chevron-left': view_variables(request)}"></i>
</div>
Controller code:
$scope.view_variables = function(req){
if (!req.enabled_variables && !req.disabled_variables) {
$http.get('/api/files/' + $scope.file_id + '/requests/' + req.id + '/variables')
.success(function(data){
variables = data.data;
req.enabled_variables = [];
req.disabled_variables = [];
for (i=0; i<variables.length; i++) {
if (variables[i].disabled == true) {
req.disabled_variables.push(variables[i]);
} else {
req.enabled_variables.push(variables[i])
}
}
});
}
req.show_variables = !req.show_variables;
}
The view_variables function doesn't return anything, so it will always be treated as false.
You want something like this:
<div class="title" ng-click="view_variables(request)">
<i ng-class="{'glyphicon glyphicon-chevron-right':!request.show_variables, 'glyphicon glyphicon-chevron-left': request.show_variables}"></i>
</div>
I think the problem is what you have going on in the ng-click attribute. By using "view_variables(request) = !view_variables(request)" are you not calling the view_variables function twice? Also, it seems strange to be assigning a value to a function call.
I would just keep ng-click="view_variables(request)" as you had in the first line of code, then have the view_variables function set a boolean somewhere in scope ($scope.data.view_vars) and have that determine ng-class for your i element.
Good luck!
--EDIT: Now that you've put up your controller, req.show_variables looks like a useful candidate
Calling a function inside ng-class is a bad idea. Why don't you use a flag for it.
eg.
inside controller-
$scope.view_variables = function(request){
//your code
$scope.isExpanded = !$scope.isExpanded;
};
and in html
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon" ng-class="{'glyphicon-chevron-right':!isExpanded, 'glyphicon-chevron-left':isExpanded}"></i>
</div>
May be Better this way using ng-show directive:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right" ng-show="!view_variables(request)"></i>
<i class="glyphicon glyphicon-chevron-left" ng-show="view_variables(request)"></i>
</div>
You could use ng-if directive like so:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right" ng-if="!view_variables(request)"></i>
<i class="glyphicon glyphicon-chevron-left" ng-if="view_variables(request)"></i>
</div>
assuming view_variables(request) returns true or false... maybe could replace it for req.show_variables.

How to trigger ng-click inside ng-repeat angularJS

ng-click does not work inside ng-repeat. I have read all the guides and similar questions, but nothing work in my code. If I click on the tag inside the ng-repeat nothing happen, but if I click on my button the function is called.
html
<div ng-repeat="sykdom in sykdommer" ng-model="sykdom.name" ng-click="test();">
<a class="item item-icon-right" href="#" ng-click="test();" >
{{sykdom.name}}
<i class="icon ion-ios-arrow-right"></i>
</a>
</div>
<button ng-click="test()> test </button>
JS
$scope.sykdommer = [{name:'test1'},
{name:'test2'},
{name:'test3'}];
$scope.test = function(){
alert('you clicked!');
};
I have tried with ng-click="$parent.test()" and ng-model="sykdom.name" without any luck. Please help, really stuck on this problem :(
Here is an example i've made with your data: http://plnkr.co/edit/o4sqPd
Template should be like:
<div ng-repeat="sykdom in sykdommer">
<a class="item item-icon-right" href="#" ng-click="test(sykdom.name);" >
{{sykdom.name}}
<i class="icon ion-ios-arrow-right"></i>
</a>
</div>
You should use ng-model directive only in case if it's a part of you changeable data - in input/textarea etc. tags (documentation: https://docs.angularjs.org/api/ng/directive/ngModel)

changing main content on ng-repeat item click

here is the plunker:
http://plnkr.co/edit/Qj2yxQuT7SZ19u3vuXyq?p=preview
like an inbox.
<div class="col-xs-4 leftnav">
<button class="btn btn-primary btn-block">Add News</button>
<br>
<article ng-repeat="x in issues | filter:query" ng-click="makeActive(i)">
<h4>{{x.title}}</h4>
<p>{{x.message | limitTo:numLimit}}</p>
Read More..
</article>
</div>
<div class="col-xs-8 main-content">
<h2>News</h2>
<hr>
<article ng-repeat="x in issues">
<h3 >{{x.title}}</h3>
<p>{{x.priority}}</p>
<p class="lead">{{x.author}} - 6/12/2014</p>
<!-- ng-if="x.author == 'Andy' " -->
<hr>
<p>{{x.message}}</p>
Read More
<hr>
</article>
</div>
having a list of items ng-repeat on the left, then selecting the main content (on the right) from the options, then displaying the full content as the main selection.
ng-if ? ng-show ?
not sure how well I've described this but it should be pretty obvious from the fiddle.
thanks in advance.
I modified your plnkr http://plnkr.co/edit/9qZsp2o22L5x1a0JofPy?p=preview
I create a currectIssue variable for your right content display.
In left content, Read More.. has been change to <a ng-click="showIssue(x)">Read More..</a>
updated plunk: http://plnkr.co/edit/hGsdkybRMoRct8VykCcB?p=preview
well, you might consider:
- use another scope variable to display the selected item from the object
- I'd use ng-if in this case as that will create/destroy the content as needed
// controller
$scope.selectIssue = function(x) {
$scope.issue = x;
}
$scope.selectIssue($scope.issues['1']);
//view
<article>
<h3 >{{issue.title}}</h3>
<p>{{issue.priority}}</p>
<p class="lead">{{issue.author}} - 6/12/2014</p>
<div ng-if="issue.author == 'Andy'">
<hr>
<p>{{issue.message}}</p>
Read More
<hr>
</div>
</article>

How to show div when link is clicked with ng-show angular js

first off, i have links from a json and display it using ng-repeat and i want to know if its best practise to load all object property (in a div) corresponding to its link and hide it so when you click a link, the corresponding div shows.
I'm thinking about the worst case scenario, were we have about a 100 links and the load all corresponding divs and hide it o_O
So this is my html:
<a href="">
<div ng-model="showModal" class="contentItem" ng-repeat='meal in recipes | filter:searchText' ng-style="{'background-image':'url({{ meal.url }})'}">
<span id="contentItemHeader">{{ meal.title }}</span>
<span id="contentItemLevel">{{ meal.level }}</span>
</div>
</a>
This is the div (modal) i want to display in full screen:
<div ng-show="showModal" ng-repeat='meal in recipes'>
<span>{{ meal.url }}</span>
<span>{{ meal.method }}</span>
<span>{{ meal.ingredients }}</span>
</div>
Use case is:
-all links loads
-click a link
-corresponding div shows
Thats it ! just like when you see a list of videos on youtube, you click one, then the video page opens but as a modal (same page)
Thanks alot,
regards
You can utilize $modal service from the UI Bootstrap, define template for meal's modal and attach ng-click handler on each individual meal in ng-repeat. In click handle you can open modal and pass meal instance to modal's scope:
View:
<div ng-repeat='meal in recipes' ng-click='selectMeal(meal)'>
{{meal.title}}
</div>
Conrtoller:
$scope.selectMeal = function(meal) {
var dialogScope = $scope.$new(true);
dialogScope.meal = meal;
var modalInstannce = $modal.open({
templateUrl: 'meal-dialog.html',
scope: dialogScope
});
};
Modal template:
<div class="modal-header">
<h3 class="modal-title">{{ meal.title }}</h3>
</div>
<div class="modal-body">
<div>{{ meal.url }}</div>
<div>{{ meal.method }}</div>
<hr />
<h4>Ingridients</h4>
<ul >
<li ng-repeat='ingridient in meal.ingridients' >{{ingridient.name}} : {{ingridient.amount}}</li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="$close()">Close</button>
</div>
Plunker here
To show div in question, when meal selected, introduce new selectedMeal property in $scope and use it in modal template, remove ng-repeat from modal div and set selectedMeal and showModal in selectMeal function:
$scope.selectMeal = function(meal) {
$scope.selectedMeal = meal;
$scope.showModal = true;
};
<div ng-show="showModal" >
<span>{{ selectedMeal.url }}</span>
<span>{{ selectedMeal.method }}</span>
<span>{{ selectedMeal.ingredients }}</span>
</div>
if your worried about performance of having all the divs exist, but hidden, consider using ng-if instead of ng-show. ng-if does not create the dom element if the expression is false.
<div ng-if="expression">
//element exists if 'expression' is true
</div>
if you are ok to ahead with angular-ui then i think the accordian fits the requirement perfectly... [here's the link for angular-ui's the accordian] directive 1
angular-ui is the pure angularjs implementation of all twitter bootstrap components.
<accordion close-others="oneAtATime">
<accordion-group heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
This content is straight in the template.
</accordion-group>
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
</accordian>
you can have either one or all user selected link detail section open at a time...

Resources