I'm using the angular-isotope plugin to repeat multiple quotes in a masonry grid. My goal is to add multiple unique tags to each quote with each tag having its own unique filter class so that when you click the tag, only tags from that filter appear. Currently, the functionality works fine with just a single tag:
HTML:
<div class="quotes js-masonry" isotope-container="isotope-container">
<div class="quote-col {{item.class}}" ng-repeat="item in quotes" isotope-item="isotope-item">
<div class="quote-single">
<div class="quote-quote">"{{item.quote}}"</div>
<div class="quote-author">
<a class="filter-click" data-filter="{{item.dataFilter}}">- {{item.author}}</a>
</div>
<div class="quote-bottom clearfix">
<span class="quote-share">
<img src="img/icons/facebook.png">
<img src="img/icons/twitter.png">
</span>
<span class="quote-tags" ng-repeat="?">
<a class="filter-click" data-filter="{{item.tagFilter}}">{{item.tag}}</a>
</span>
</div>
</div>
</div>
Angular Controller:
var demo = angular.module('angular-isotope-demo', []);
demo.controller('QuoteController', function QuoteController($scope) {
$scope.quotes = [
{
"quote":"It is better to lead from behind and to put others in front, especially when you celebrate victory when nice things occur. You take the front line when there is danger. Then people will appreciate your leadership.",
"author":"Nelson Mandela",
"tag": [
"Leadership",
"Second Class"
],
"class":"mandela leadership",
"dataFilter": ".mandela",
"tagFilter": [
".leadership",
".second-class"
]
}
]
});
My question is, how do I repeat that item tag (i.e. "Leadership", "Second Class") and attach it to that ".second-class" in the tagFilter so it looks like this?:
I hope this is clear to understand.
You will likely have a nested ng-repeat. So turn your quote.tag element into an array and do something like this:
<div ng-repeat="tag in item.tags">
<a class="filter-click" data-filter="{{tag.filter}}">{{tag.tag}}</a>
{{ $last ? '' : ( $index < item.tags.length-2 ) ? ', ' : '' }}
</div>
If you wish to have different classes for each item, then I would have another element within item.tags, say item.tags.classes and then do this:
<a class="filter-click" ng-class="tag.classes" data-filter="{{tag.filter}}">{{tag.tag}}</a>
Your data will need to be restructured for this to work:
{
"quote":"It is better to lead from behind and to put others in front, especially when you celebrate victory when nice things occur. You take the front line when there is danger. Then people will appreciate your leadership.",
"author":"Nelson Mandela",
"tags": [
{
"tag":"Leadership",
"filter":".leadership",
"classes": "second-class"
}
],
"class":"mandela leadership",
"dataFilter": ".mandela",
}
Related
I'm using Angular 4 and I want to loop through an array of objects and display the information in Angular Material grids tiles. My html (app.component.html) looks a bit like this
<div class="list" *ngIf="listContacts == true">
<mat-grid-list cols="3" rowHeight="2:1" *ngFor="let i of contacts">
<mat-grid-tile>
<div class="card">
<img src={{contacts[i].image}} alt="picture">
<h2>{{contacts[i].name}}</h2>
</div>
</mat-grid-tile>
</mat-grid-list>
</div>
And contacts is an array of objects inside app.component.ts. There are NINE objects within contacts but for simplicity I've only put two here.
export class AppComponent {
// array of contact objects
contacts = [
{
name: "Robbie Peck",
image: "src/assets/robbie.jpg",
},
{
name: "Jenny Sweets",
image: "src/assets/jenny.jpg",
},
...
]
}
So rather than have nine different 's appear, each with their own information (looping i through contacts), I only have one and the console shows an error where it doesn't recognize contacts[i]. What have I done wrong? How can I get the to have 9 's, each with name and image i within the contacts object in the typescript (app.component.ts) file?
You don't have to pass the index, you can just use the variable i and access i.image and i.name
<mat-grid-list cols="3" rowHeight="2:1" *ngFor="let i of contacts" >
<mat-grid-tile>
<div class="card">
<img src={{i.image}} alt="picture">
<h2>{{i.name}}</h2>
</div>
</mat-grid-tile>
I am making a simple demo of nested ng-repeat with some condition.it is not printing any values why ?
Actually I am trying to get below result after iteration of two objects
Expected result
ght nor
abc pqr
code pen or plunker
\
<ion-scroll scrollbar-y="true">
<div class="row rowclass" ng-repeat="column in a ">
<div class="col brd text-center collapse-sm columnCss" ng-repeat="field in column.columns" ng-show="b[$index].fieldNameOrPath===field.fieldNameOrPath">{{field.value}}</div>
</div>
</ion-scroll>
Actually I have two object ..having one key inside I need to show those value which is equal .but i am not getting expected result why ?
You need to update
ng-show="b[$index].fieldNameOrPath===field.fieldNameOrPath"
to
ng-show="b[$index-1].fieldNameOrPath===field.fieldNameOrPath"
And in your json, fieldNameOrPath property is different in a and b like in a it is "Sub" and in b it is "Subject", so either update a or b, so that property fieldNameOrPath is same at both the places.
Here is the answer with example.
Also in script.js file i have corrected some type mistakes.
ng-show="b[$index-1].fieldNameOrPath===field.fieldNameOrPath"
While it is technically possible to do this with your current data set, I'd very much recommend changing your data model to look something like this:
$scope.dataRows = [
{
ID: "00TK000000INaMXMA1",
Subject: "ght",
Priority: "normal"
},
{
ID: "00TKabc",
Subject: "abc",
Priority: "pqr"
}
];
And your HTML to something like this:
<ion-scroll scrollbar-y="true">
<div class="row rowclass" ng-repeat="row in dataRows">
<div class="col brd text-center collapse-sm columnCss">
{{row.Subject}}
</div>
<div class="col brd text-center collapse-sm columnCss">
{{row.Priority}}
</div>
</div>
</ion-scroll>
However, if for some reason this just isn't possible (data feed from some other place etc), then here is how I fixed your table issues:
1 : your fieldNameOrPath attributes didn't match (one was "Pri" and "Sub" and the other was "Priority" and "Subject").
2: You will need to add another ng-repeat unfortunately. Your indexes don't line up correctly because you have 3 fields in your data and 2 in your data columns. I've made a Plnkr fork for you that solves your problem (minus some css styling stuff) but I'd only recommend using it if you cannot change your data model.
http://plnkr.co/edit/3K3zKenGHG4hARkXmUTp?p=preview
I have json object and I need to iterate that object in angular. I will tell you my problem. I have one button. On click of that button user can select multiple elements. I take example ('a','b','c'...so on). When user select 'a' and close the pop up I need to show this result.
Expected result when 'a' is selected
A // header
A S //names
A p
When user select 'A' its search from showTableData and show the names below header:
"A": [
{ "name":"A S"},
{ "name":"A p"}
],
When user select 'A' and 'B' then expected result:
A B // headers
A S B BS
A P B Bp
so on..
Actually I am able to print header if user select any thing 'A' .'B','C'..so on. I don't know how to print it corresponding names below header.
Here is my code: http://codepen.io/anon/pen/zGNLdR
<div class="row">
<div ng-repeat="d in data">
<div class="col" ng-show="d.checked">{{d.name}}</div>
</div>
</div>
is there any other way to take json object to show the expected result ..
can I map different way data with showTabledata so that i will get expected result ?
$scope.showTableData={
"A": [
{ "name":"A S"},
{ "name":"A p"}
],
"B": [
{ "name":"B BS"},
{ "name":"B Bp"}
],
"c": [
{ "name":"c c"},
{ "name":"c c"}
],
"d": [
{ "name":"d dS"},
{ "name":"d dp"}
],
"E":[
{ "name":"E ES"},
{ "name":"E Ep"}
]
};
I think that the simplest solution is just adding another div and iterate in it over your showTableData variable, but only by keys which were selected.
<div ng-repeat="d in data">
<div class="col" ng-show="d.checked">{{d.name}}</div>
<div class="col" ng-show="d.checked"
ng-repeat="nameObject in showTableData[d.name]">
{{nameObject.name}}
</div>
</div>
Example on codepen.
There are some things which can be refactored, but I hope, that you'll get the idea.
There is a little bit cleaner solution with using of filter. With this approach you can remove your ng-show inside ng-repeat.
<div ng-repeat="d in data | filter:{checked: true}">
<div class="col">{{d.name}}</div>
<div class="col" ng-repeat="nameObject in showTableData[d.name]">
{{nameObject.name}}
</div>
</div>
Example.
Trying this:
<div ng-repeat="store in something111.company2.store">
{{store.name}}
<div ng-repeat="section in something111.company2.store.section">
{{section.name}}
</div>
</div>
Getting this:
DePere
Green Bay
This is my user.company2:
{
"_id":"5473fc8c14034efd3c2b3d58",
"name":"Festival",
"__v":0,
"store":[{
"_id":"5473fc8c14034efd3c2b3d59",
"name":"DePere",
"__v":0,
"section":
[{
"_id":"5478b54c945d4c00001aa5f9",
"name":"Deli",
"__v":0}]},
{
"_id":"54747f498e16571b6049e266",
"name":"Green Bay",
"__v":0,
"section":
[{
"_id":"547930057f7aa70000ee568f",
"name":"Produce",
"__v":0}]}]}
Produce should be showing up under Green Bay and Deli should be showing up under DePere, but they're not. company2.store works but company2.store.section doesn't... or something's wrong with the ng-repeat.
What should I do to fix it? Thanks!
For inner ng-repeat, begin the 'path' at the point where you finish the outer one:
<div ng-repeat="store in something111.company2.store">
{{store.name}}
<div ng-repeat="section in store.section">
{{section.name}}
</div>
</div>
In this case, inner ng-repeat will iterate over the collection stored in section property of every element of array stored in user.company2.store. Currently, you're trying to access user.company2.store.section directly - and fail, because there's no such property as section in user.company2.store array.
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>