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

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...

Related

In what scope is ng-repeat "as alias" available

I'm using angular 1.4.8. I want to save filtered result from ng-repeat and use it to determine whether to enable a "load more" button at the bottom of the list. I have looked at this question:
AngularJS - how to get an ngRepeat filtered result reference
And many others, they suggest to use "as alias" from ng-repeat, here's what my code looks like:
<ul class="media-list tab-pane fade in active">
<li class="media">
<div ng-repeat-start="item in items | limitTo: totalDisplayed as filteredResult">
{{item}}
</div>
<div class="panel panel-default" ng-repeat-end>
</div>
<div>
{{filteredResult.length}}
</div>
</li>
</ul>
<button ng-click="loadMore()" ng-show="totalDisplayed <= filteredResult.length">
more
</button>
However, I found filteredResult.length is displayed fine right after ng-repeat, but the button is never shown. If I try to display filteredResult.length in where the button is, it will show null.
So is there a rule for "as alias" scope? I've seen plenty of examples work but mine doesn't, what am I missing here?
EDIT:
The accepted answer uses controllerAs which indeed will resolve the problem. However, charlietfl's comment using ng-init to save filteredResult to parent scope is also very neat and that's the solution I use in my code eventually.
Probably some of classes in your <ul class="media-list tab-pane fade in active"> or <li class="media"> is selector for a directive that would have its own scope. So you store filteredResult in e.g. tab-pane's scope and then try to have access out of it's scope in outside of ul tag.
Try to use Controller as instead of scope:
angular
.module('plunker', [])
.controller('MainCtrl', function() {
vm = this;
// make an array from 1 to 10
var arr = [];
while (arr.length < 10) {
arr.push(arr.length + 1)
};
vm.items = arr;
vm.totalDisplayed = 5;
vm.filteredResult = [];
});
<body ng-controller="MainCtrl as main">
{{main.items}}
<ul class="media-list tab-pane fade in active">
<li class="media">
<div ng-repeat-start="item in main.items | limitTo: main.totalDisplayed as filteredResult">
{{item}}
</div>
<div class="panel panel-default" ng-repeat-end>
</div>
<div>
filteredResult = {{main.filteredResult = filteredResult}}
</div>
</li>
</ul>
<button ng-click="loadMore()" ng-show="main.totalDisplayed <= main.filteredResult.length">
more
</button>
</body>
http://plnkr.co/edit/drA1gQ1qj0U9VCN4IIPP?p=preview

show a div with ng if ionic

<ion-view cache-view="false">
<div class="navbar-fixed-top navbar-header bar bar-header " ng-if="showHeader">
<div class="container row">
<div>
<a class="navbar-brand" href="#">
<h1>ROCK 'N' GRILL<br>
<span>Pitampura New Delhi...</span></h1>
</a>
</div>
{{showSubHeader}}
<div ng-if="showSubHeader===true" class="topPull" draggable >
<button ng-if="showSubHeader" class="button-icon"><img src="img/topImg.jpg"></button>
</div>
</div>
</div>
</ion-view>
The value of showSubHeader changes to false but yet I see the div in my view. How do I update view to not show the div when the value is false?
Edit:
This is veiw attached to an abstract state so I believe , the abstract state is not updated when views are switched. How do I reload header when views change or switch?
Instead of using ng-if you could use ng-show. So when showSubHeader is false, your div won't be shown. Have a look here: https://docs.angularjs.org/api/ng/directive/ngShow

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)

AngularJS - Show and Hide multiple content

In AngularJS, to simply show a field through an a tag, I would do in this way:
<div ng-show="aField">Content of aField</div>
<a ng-click="aField=true">Show aField</a>
until here, no problem.
I would like now to put more buttons and fields so that, when I click on A it shows the content of A, then when I click on button B, content of A disappears and content of B appears.
How can I do this? Thank you.
UPDATE
Thank you everyone for your solutions, they works! Now, I am doing a template for every content of and because I have much data to show but all in the same structure.
Here the index.html
<div ng-model="methods"
ng-include="'templateMethod.html'"
ng-repeat = "method in methods">
here the script.js:
function Ctrl($scope) {
$scope.methods =
[ { name: 'method1',
description: 'bla bla bla',
benefits: 'benefits of method1',
bestPractices : 'bestPractices',
example: 'example'},
{ name: 'method2',
description: 'bla bla bla',
benefits: 'benefits of method2',
bestPractices : 'bestPractices',
example: 'example'} ];
}
and here the templateMethod.html:
<table>
<tr>
<td>
<div ng-show="toShow=='{{method.name}}Field'">
<h3>{{mmethodethod.name}}</h3>
<p>
<strong>Description</strong>
{{method.description}}
</p>
<p>
<strong>Benefits</strong>
{{method.benefits}}
</p>
<p>
<strong>Best practices</strong>
{{method.bestPractices}}
</p>
<p>
<strong>Examples</strong>
{{method.example}}
</p>
</div>
</td>
<td class = "sidebar">
<ul>
<li><a ng-click="toShow='{{method.name}}Field'" class="{{method.name}} buttons">{{method.name}}</a></li>
</ul>
</td>
</tr>
</table>
It works!
But: if I click the first button and then the second one, the content of the first button do not disappear, it appears under the content of the first button...
Problem with the repetition?
Thanks
It might be better to handle more complex logic in the controller, but in general think about the content of the directive strings as normal js:
<div ng-show="aField">Content of aField</div>
<div ng-show="bField">Content of bField</div>
<a ng-click="aField=true; bField=false">Show aField</a>
<a ng-click="aField=false; bField=true">Show bField</a>
Or use ng-show in concert with ng-hide:
<div ng-show="aField">Content of aField</div>
<div ng-hide="aField">Content of bField</div>
<a ng-click="aField=true">Show aField</a>
<a ng-click="aField=false">Show bField</a>
In the former strategy, nothing shows upon page load. In the latter, the bField content shows by default. If you have more than two items, you might do something like:
<div ng-show="toShow=='aField'">Content of aField</div>
<div ng-show="toShow=='bField'">Content of bField</div>
<div ng-show="toShow=='cField'">Content of cField</div>
<a ng-click="toShow='aField'">Show aField</a>
<a ng-click="toShow='bField'">Show bField</a>
<a ng-click="toShow='cField'">Show cField</a>
I'm guessing that you have a list of items and want to show each item content. Something an accordion component does.
Here is a plunker that shows how you could do it: http://plnkr.co/edit/UTf3dEImiDReC89vULpX?p=preview
Or if you want to display the content on the same place (something like a master detail view) you can do it like this: http://plnkr.co/edit/68DJHL582oY4ecSiiUdE?p=preview
simply use one variable which content is visible. http://jsfiddle.net/gjbw7/
<a ng-click="show='a'">Show aField</a>
.
<div ng-show="show=='a'">Content of aField</div>
I would recommend to create a service in case your fields belong to different controllers.
Service:
App.factory('StateService', function() {
return {
openPanel: ''
};
});
Injecting the service in a Controller:
App.controller('OneCtrl', function($scope, StateService) {
$scope.stateService = StateService;
});
Finally using it a view:
<a ng-click="stateService.openPanel='home'">Home</a>
<div ng-show="stateService.openPanel == 'home'">Content of Home</div>
Demo: http://jsfiddle.net/codef0rmer/BZcdu/
Try this way.
<div>{{content}}</div>
<a ng-click="content='a'">Show aField</a>
<br>
<a ng-click="content='b'">Show bField</a>
<br>
<a ng-click="content='c'">Show cField</a>
<br>
<a ng-click="content='d'">Show dField</a>
<br>
<a ng-click="content='e'">Show eField</a>
<br>
<a ng-click="content='f'">Show fField</a>
Take a look at the ng-switch directive.
<div ng-switch="aField">
<div ng-switch-when="someValue1">
HTML content that will be shown when the aField variable value is equal to someValue1
</div>
<div ng-switch-when="someValue2">
HTML content that will be shown when the aField variable value is equal to someValue2
</div>
<div ng-switch-default>
This is where the default HTML content will go (if aField value is not equal to any of the ng-switch-when values)
</div>
</div>

Bootstrap collapse not collapsing back

I have a page where I have included the (Twitter) bootstrap.
On this page I have a prefectly working accordion and within that accordion I have a collapsable div. See the code below:
<div class="accordion" id="checkListAccordion">
<div ng-repeat="item in items" class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#checkListAccordion" href="#collapse{{item.$$hashKey}}">{{item.name}}</a>
</div>
<div id="collapse{{item.$$hashKey}}" class="accordion-body collapse">
<div class="accordion-inner">
<div class="container-fluid">
<div class="row-fluid">
<div class="badges span12">
<span class="badge badge-info" data-toggle="collapse" data-target=".info{{item.$$hashKey}}"><i class="icon-info-sign icon-white"></i></span>
<div class="info{{item.$$hashKey}} collapse in">
{{item.info}}
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
some text
</div>
</div>
</div>
</div>
</div>
</div>
Now, when I click the info badge, the div with the corresponding class is folding open. But it never folds back when I click it again. Only when I wrap in in a navbar and navbar-inner, it folds back....but of course, I don't want that.
Any help on this?
When i add a controler to your code all seems to work as expected:
angular.module('plunker',[]);
function AccordionDemoCtrl($scope) {
$scope.oneAtATime = true;
$scope.items = [
{
name: "Dynamic Group Header - 1",
info: "Dynamic Group Body - 1"
},
{
name: "Dynamic Group Header - 2",
info: "Dynamic Group Body - 2"
}
];
}
See also: http://plnkr.co/nX4kvMThA0bYwcbXZS7t May be there will be a problem with the versions you use? I used jQuery 1.9.1, Twitter Bootstrap 2.3.1 and angularJS 1.0.7 (see: Angular JS Bootstrap Accordian Example).
btw have you consider to use UI Bootstrap (http://angular-ui.github.io/bootstrap/) see: http://plnkr.co/u7l6nrkPZM8ZJtA08RNP (thanks to winkerVSbecks who answered Howto set template variables in Angular UI Bootstrap? (accordion))

Resources