set all ng-if to false on click except clicked item - javascript

I have an ng-repeat which has a button that has a function that toggles an ng-show element inside that ng-repeat.
The inside the class movie_option span has an ng-click=toggleInfo($index):
And the div additional_info has an ng-show that shows or hides an element.
<ul ng-cloak="showResult">
<li class="search_results" ng-repeat="movie in movies | orderBy: '-release_date' track by $index">
<div class="movie_info">
<div class="movie_options">
<div class="slide">
<span class="movie_option">
<span><i class="fa fa-question-circle" aria-hidden="true" ng-click="toggleInfo($index)"></i></span>
</span>
</div>
</div>
</div>
<div class="additional_info" ng-show="hiddenDiv[$index]">
{{movie.overview}}
</div>
</li>
</ul>
When a user clicks on the icon it calls this function:
$scope.toggleInfo = function (index) {
$scope.hiddenDiv[index] = !$scope.hiddenDiv[index];
}
This toggles the ng-show state from the hiddenDiv ng-show. This works fine.
What I wanted to do is put all hiddenDiv states on false except the one that is clicked so only one ng-show would be true.

That's a pure algorithm problem, not related to Angular.
Instead of having a boolean per item, it would be much simpler to just remember the element (index) that should be displayed:
<ul ng-cloak="showResult">
<li class="search_results" ng-repeat="movie in movies | orderBy: '-release_date' track by $index">
<div class="movie_info">
<div class="movie_options">
<div class="slide">
<span class="movie_option">
<span><i class="fa fa-question-circle" aria-hidden="true" ng-click="model.displayedIndex = $index"></i></span>
</span>
</div>
</div>
</div>
<div class="additional_info" ng-show="$index === model.displayedIndex">
{{movie.overview}}
</div>
</li>
</ul>
And in your controller $scope.model = {}
Fiddle: http://jsfiddle.net/6dkLqgfL/

I think this would do:
$scope.toggleInfo = function(index) {
for(var i in $scope.hiddenDiv) {
if(index != i)
$scope.hiddenDiv[i] = false;
}
$scope.hiddenDiv[index] = !$scope.hiddenDiv[index];
}

You could just manually turn all the hiddenDiv elements to false when the toggleInfo function is fired.
$scope.toggleInfo = function(index){
for(int i = 0; i<($scope.hiddenDiv).length; i++)
$scope.hiddenDiv[i] = false;
$scope.hiddenDiv[index] = !$scope.hiddenDiv[index];
}
See if this works?

Related

Target only 1 button in Angular

Im getting the values in a div from the DB and displaying using ng-repeat:
<div ng-controller = "myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{'active': isActive}" ng-click="test()" >me</button>
</div>
</div>
In my controller I have:
$scope.test= function(){
$scope.isActive = !$scope.isActive;
}
I have defined a class isActive in my css and that is applied/removed to the button on click. There are 5 results so 5 divs are created cause of ng-repeat and 5 buttons(1 for each respective div). The problem is that every button (all 5 of them) is getting that class. I want the class to be applied/removed only to the button clicked. How can I achieve this?
You can try something like this :
<div ng-controller="myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{ active : name.isActive }"
ng-click="name.isActive = !name.isActive">me</button>
</div>
</div>
Hope this will help.
You need to keep track of each button status.
One way will be to passing the name or anything that uniquely identify the button to your function:
<div ng-controller = "myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{'active': buttons[name].isActive}" ng-click="test(name)" >me</button>
</div>
</div>
$scope.buttons = {};
$scope.test= function(name){
$scope.buttons[name].isActive = !$scope.buttons[name].isActive;
}
I created a plunk that answers this question without modifying your source array.
Your function becomes
vm.test = function(buttonIndex) {
//Clear the class if you press the same button again
if (vm.buttonIndex === buttonIndex) {
vm.buttonIndex = undefined;
} else {
vm.buttonIndex = buttonIndex;
}
};
And your HTML is
<div ng-repeat="name in main.names track by $index">
<h4>{{name.name}}</h4>
<button ng-class="{'active': main.buttonIndex===$index}" ng-click="main.test($index)">me</button>
</div>

ng-repeat toggle slide, but others should be close

I am using below code for slide toggle, it
<div ng-repeat="item in $ctrl.searchitems track by $index">
<div class="quickinfo-overlap"> Content here...
<a class="btn-link" ng-click="$ctrl.quickinfoToggle(item)">quick info</a>
</div>
</div>
And I am using ng-repeat, so it is showing list, I want others list should be close or quickinfo false. so can I do?
This is the controller code:
function listingController($scope) {
var vm = this;
vm.quickinfo = false;
vm.quickinfoToggle = function(event) {
event.quickinfo = !event.quickinfo;
};
};
HTML:
<div ng-repeat="item in $ctrl.searchitems track by $index">
<div class="quickinfo-overlap"> Content here...
<a class="btn-link" ng-click="$ctrl.quickinfoToggle(item,$index)">quick info</a>
</div>
<div>
DIV that needs to be toggled on click
</div>
</div>
Javascript:
function listingController($scope) {
var vm = this;
$scope.toggleList = [];
for(var i=0;i< $scope.searchitems.length;i++)
$scope.toggleList[i] = false;
vm.quickinfoToggle = function(event,index) {
for(var i=0;i< $scope.toggleList.length;i++)
$scope.toggleList[i] = false;
$scope.toggleList[index] = true
event.quickinfo = !event.quickinfo;
};
};
while looping with ng-repeat to show the items, set ng-show:
<div class="quickinfo slide-toggle" ng-show="quickinfo == 1" ng-cloak>
Content here ....
</div>
<a class="btn-link" ng-click="quickinfo = 1">quick info</a>
Of course 1 is not fixed number, it should be unique to each item, like the index or id of the item.
The idea is when clicking the quickinfo link you assigned the clicked item's id not assign true\false to the quickinfo, and in ng-show check if the current id assigned to quickinfo is the same as this item id (or index).
Of course variable names can be changed.

Bind paired data in object to another element outside ng-repeat - angular

I have this array of objects that I need to work with:
$scope.pdfs = [
{ "pdf_title": "Corporate Hire", "attached_file": "http://file1.jpg"},
{ "pdf_title": "Wedding Hire", "attached_file": "http://file2.jpg"},
{ "pdf_title": "Filming Hire", "attached_file": "http://file3.jpg"}
];
The pdf_file value is ng-repeated in li's.
What I want to do is if that li is clicked, to push its paired to another div, say the src for an href.
Here are my workings, but not quite correct:
Controller function:
$scope.bindWithFile = function(value) {
var currentValue = $scope.corpResult = value;
// pdfs support
var pdfs = $scope.pdfs;
for (var i = pdfs.length - 1; i >= 0; i--) {
if (currentValue == hasOwnProperty(key[pdfs])) {
value[pdfs] = $scope.corpLinkHref;
}
};
Markup:
<div class="w-12" ng-controller="corpHireController">
<div class="c-6-set">
<ul>
<li ng-repeat="pdf in pdfs" class="col-7 link link-inherit" ng-click="bindWithFile(pdf.pdf_title)">{{::pdf.pdf_title}}</li>
</ul>
</div>
<div class="c-6-set">
<div class="w-12">
<i class="fs-4 col-7 icon icon-pdf"></i>
</div>
<span class="col-7 h4" ng-bind="corpResult"></span>
<button ng-href="{{::corpLinkHref}}" class="button green2-button smaller-letters full-width">Download</button>
</div>
</div>
What is needed:
Clicking on the titles on the left, binds the pdf_title under the pdf icon and binds the attached_file to the button's href
Instead of passing the title of the selected pdf, why not passing the whole object. This way you don't have to performance any find or search function.
Markup:
<div class="w-12" ng-controller="corpHireController">
<div class="c-6-set">
<ul>
<li ng-repeat="pdf in pdfs" class="col-7 link link-inherit"
ng-click="bindWithFile(pdf)">
{{::pdf.pdf_title}}
</li>
</ul>
</div>
<div class="c-6-set">
<div class="w-12">
<i class="fs-4 col-7 icon icon-pdf"></i>
</div>
<span class="col-7 h4" ng-bind="corpResult"></span>
<button ng-href="{{::corpLinkHref}}"
class="button green2-button smaller-letters full-width">
Download
</button>
</div>
</div>
Controller
$scope.bindWithFile = function(selectedPdf) {
$scope.corpResult = selectedPdf.pdf_title;
$scope.corpLinkHref = selectedPdf.attached_file;
}

Angular Js ng-init is not working properly inside ng-repeat while setting a variable

I have a ng-repeat where i am checking a if condition and at the end of each repeation of loop i am setting a variable to a value from ng-repeat
Here is my variable which i want to set inside the ng-repeat
$scope.prvSid = "";
Here is my ng-repeat code
<ul class="chats" ng-repeat="chatData in chatboxData">
<li ng-class="{ 'out': chatData.sender_id == user_id , 'in': chatData.sender_id != user_id }">
{{ prvSid }}
{{ chatData.sender_id }}
<span ng-if=" prvSid != chatData.sender_id ">
<img class="avatar" alt="" src="{{ url('default/img/user_default_logo.jpg') }}" />
</span>
<div class="message">
<span class="body"> {{ chatData.message }} </span>
</div>
<span ng-init="prvSid = chatData.sender_id"></span>
{{ prvSid }}
</li>
</ul>
The problem which i am facing here is that whenever i print these values inside the ng-repeat then prvSid and chatData.sender_id is printing the same id the value of chatData.sender_id even for the first iteration and that's why this
<span ng-if=" prvSid != chatData.sender_id ">
condition is not working and my image is not displaying because for the first iteration the condition should be true because prvSid is "" and chatData.sender_id has some id in it
The purpose of this is to
Henry Zou the purpose is to not show profile picture for two or more messages submitted by same user (if the sender_id is same)Then dont display the profile image.When the new message comes from another sender which means sender_id is different then show the profile image
at first the prvSid will be null so it will show the image because condition will not match at the end of each iteration i will set the prvSid to the current iteration sender_id to match this prv_id with sender_id in the next iteration
i am also getting messages after two seconds and then i am adding the new records in the chatboxdata if they dont exist in it
$scope.getlasttwosecMsgs = function(user_id_chat,chat_id,user,chatboxData,is_new) {
$http.get(url+'/getlasttwosecMsgs/'+chat_id).success(function(data){
angular.forEach(data, function(value, key) {
var exists = $scope.containsObject(value,chatboxData);
if (!exists) {
$scope.chatboxData.push(value);
console.log($scope.chatboxData);
};
});
});
}
$scope.containsObject = function(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (angular.equals(list[i], obj)) {
return true;
}
}
return false;
};
This new code snippet will check current userID against a list of users in the chatbox. For all users that's not the current user, show content.
approach #1 (preferred)
angular
.module('app', [])
.controller('myCtrl', function(){
var vm = this;
var prvSid = null;
vm.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
vm.chatboxData.forEach(function(chatbox){
if(prvSid !== chatbox.id){
chatbox.showIcon = true;
}
prvSid = chatbox.id;
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="app">
<div ng-controller="myCtrl as vm">
<ul class="chats" ng-repeat="chatData in vm.chatboxData">
<li>
<span ng-if="chatData.showIcon ">
ICON
</span>
{{::chatData.id}}
</li>
</ul>
</div>
</div>
approach #2
angular
.module('app', [])
.controller('myCtrl', function(){
var vm = this;
vm.prvSid = null;
vm.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="app">
<div ng-controller="myCtrl as vm">
<ul class="chats" ng-repeat="chatData in vm.chatboxData">
<li>
<span ng-if="chatData.showIcon ">
ICON
</span>
{{::vm.prvSid}} {{::chatData.id}}
<span ng-init="chatData.showIcon = (vm.prvSid !== chatData.id)"></span>
<span ng-init=" vm.prvSid = chatData.id"></span>
</li>
</ul>
</div>
</div>
approach #3 (without using controllerAs syntax)
angular
.module('app', [])
.controller('myCtrl', function($scope){
var prvSid = null;
$scope.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
$scope.chatboxData.forEach(function(chatbox){
if(prvSid !== chatbox.id){
chatbox.showIcon = true;
}
prvSid = chatbox.id;
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="app">
<div ng-controller="myCtrl">
<ul class="chats" ng-repeat="chatData in chatboxData">
<li>
<span ng-if="chatData.showIcon ">
ICON
</span>
{{::chatData.id}}
</li>
</ul>
</div>
</div>
OLD ANSWER
In the video AngularJS MTV Meetup: Best Practices (2012/12/11), Miško
explains "..if you use ng-model there has to be a dot somewhere. If
you don't have a dot, you're doing it
wrong.."
ng-repeat creates an inherited scope (think javascript prototype) for each item.
This code below will create $scope.prvSid for each item in the array and the value will always be chatData.sender_id.
<span ng-init="prvSid = chatData.sender_id"></span>
If you meant it to only have 1 instances of prvSid id, then what you'll need to do is initialize prvSid variable at the parent scope first (or use the dot(.) rule)
<div ng-init="prvSid = null"> <!-- initializing prvSid id # parent scope -->
<ul class="chats" ng-repeat="chatData in chatboxData">
<li ng-class="{ 'out': chatData.sender_id == user_id , 'in': chatData.sender_id != user_id }">
{{ prvSid }}
{{ chatData.sender_id }}
<span ng-if=" prvSid != chatData.sender_id ">
<img class="avatar" alt="" src="{{ url('default/img/user_default_logo.jpg') }}" />
</span>
<div class="message">
<span class="body"> {{ chatData.message }} </span>
</div>
<!-- this will now update the parent scope's prvSid instead of creating a new one for each item in the array -->
<span ng-init="prvSid = chatData.sender_id"></span>
{{ prvSid }}
</li>
</ul>
</div>

How to trigger ng-hide on all elements

I have a list that when you click on an li, it reveals a hidden list of information about that person.
In the footer, theres simple navigation showing the different views and when you click, angular filters through the original list for the matched elements.
All I am stuck on is this;
if you click an li element and reveal the info for that person, then click one of the navigation buttons, it will still show that person but with the hidden element revealed...not closed.
Ideally, id prefer that when the user clicks any of the footer navigation buttons, the list reveals just the names, not the hidden info..regardless of whether it was clicked or not.
If this was just in Jquery or javascript, i would know how to approach this but, Im sure theres an 'angular specific' approach I just don't know about.
Heres the HTML:
<div ng-controller="MyCtrl">
<ul id="housewrapper" ng-cloak>
<li ng-repeat="item in house track by item.member" class="listings" ng-click="showComments = !showComments;" ng-show="([item] | filter:filters).length > 0" >
<span ng-if="item.whereHesheStands == 'oppose'"><img class="dot againstdot" src="img/against.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'leanoppose'">
<img class="dot againstdot" src="img/against.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'support'" ng-click="clickMeImg($event);">
<img class="dot supportdot" src="img/support.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'leansupport' ">
<img class="dot supportdot" src="img/support.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'unknown' ">
<img class="dot undecideddot" src="img/undecided.png">{{item.member}}
</span>
<span ng-if="item.whereHesheStands == 'undecided' ">
<img class="dot undecideddot" src="img/undecided.png">{{item.member}}
</span>
<div class="memberdetail" ng-show="showComments" ng-click="$event.stopPropagation();" >
<ul class="memberbreakdown">
<li class="partyline" >
{{item.party}} - {{item.state}}</li>
<li class="comments">
<span style="color:#a4a4a4;" ng-if="!(item.comments)">Comment not available</span>
<span>{{item.comments}}</span>
</li>
</ul>
</div>
</li>
</ul>
<div id="appfooterWrapper">
<ul id="appfooter">
<li ng-click="myFunctionRepublican();" ng-class="class">R</li>
<li ng-click="myFunctionDemocrat();" ng-class="class2">D</li>
<li ng-click="myFunctionSupport();" ng-class="class3">S</li>
<li ng-click="myFunctionOppose();" ng-class="class4">A</li>
<li ng-click="myFunctionUnknown();" ng-class="class5">U</li>
</ul>
</div>
and the javascript of the "R" navigation button
$scope.myFunctionRepublican = function() {
$('.memberdetail').removeClass('ng-show');
$('.memberdetail').bind('click');
$scope.filters = function(house) {
return house.party == 'R' ;
};
if ($scope.class === ""){
$scope.class = "rep";
$scope.class2 = "";
$scope.class3 = "";
$scope.class4 = "";
$scope.class5 = "";
}
else{
$scope.class = "";
}
$('html, body').animate({scrollTop:0}, 'fast');
var loading;
loading = true;
if (loading == true) {
setTimeout(function() {
spinner.stop();
$('.listings').not('.ng-hide').addClass('republican');
console.log($('.republican').length);
$('#housewrapper').stop().fadeIn(350).addClass(
'marginAdd');
$('#subhead').removeClass('slidedown');
$('#subhead').html('Republicans').css('color', '#d41600');
setTimeout(function() {
$('#subhead').addClass('slidedown');
}, 300);
}, 500);
}
}
Here's the Fiddle
A couple changes, attach a property onto each member.
View changes:
ng-click="item.showComments = !item.showComments;"
<div class="memberdetail" ng-show="item.showComments" ng-click="$event.stopPropagation();" >
Controller changes:
function resetShow() {
for(var i = 0, l = $scope.house.length; i < l; i++) {
$scope.house[i].showComments = false;
}
}
Then just call it when you navigate:
$scope.myFunctionUnknown = function() {
resetShow();
....
Forked Fiddle

Categories

Resources