HTML mustache templates - how to get first item of collection - javascript

I'm using mustache templates to correctly generate bootstrap accordions. Now I need to pass a prefix to the top item id = 'accorElM' and thought I could do something like this.
 
<div class="accordion" id='{{#DataResult[0].prefixID}}_accorElM'>
IE, get the first item in the collection
Is this possible to do?
Code sample:
<div class="accordion" id='accorElM'>
{{#DataResult}}
<div class="accordion-group">
<div class="accordion-heading">
<a style="text-align: left; text-decoration: none" class="accordion-toggle btn" data-toggle="collapse" data-parent='#{{prefixID}}accorEl' href='#{{prefixID}}collapseEl_{{id}}'>
<i class="icon-globe"></i> {{tipo}}<i class="icon-chevron-down pull-right"></i>
</a>
</div>
<div id='collapseEl_{{id}}' class="accordion-body collapse">
<div class="accordion-inner">
<div class="row-fluid">
<div class="span9">
<address>
<br />
{{zona}}
<br />
{{cpostal}}
<br />
{{pais}}
</address>
</div>
<div class="span3">
<div class="pull-right">
.....
</div>
</div>
</div>
</div>
</div>
</div>
{{/DataResult}}
</div>

I'm guessing your data must be something like this:
{"DataResult":[
{"prefixID":"1","name":"first"},
{"prefixID":"2","name":"second"}
]
}
but in the mustache template file, I don't think you can index the object items. The approach that I would have taken would involve manipulating the Json object in javascript(or even in the backend when constructing the object) before rendering it.
In your case, if you need the prefixID of the first item in the DataResult. you could alter the object to make it look like this:
{"DataResult":[
{"prefixID":"1","name":"first"},
{"prefixID":"2","name":"second"}
],
"theIdIWant":"1"
}
and then in the template file:
<div class="accordion" id='{{theIdIWant}}_accorElM'>
{{#DataResult}}
<div class="accordion-group">
///////
</div>
{{/DataResult}}
</div>
Hope this helps.

Related

Nested v-for in vuejs for accordian data

I am building a small application on VueJS 2.5.17 where I am having nested accordion data which I need to display through click events, I have a hierarchy of Root -> Roles -> Specialisation -> withRoles .... and so on. I am trying to get child elements on every click of their respective parents.
Following is my HTML Code:
<div class="panel-group" id="accordion1" v-for="items in accordianData">
<div class="panel my-panel-warning">
<div class="panel-heading">
<h4 class="panel-title">
<a style="color: #000; font-size: 14px" data-toggle="collapse" data-parent="#accordion1" :href="'#'+items.id">DOCUMENTED RELATIONSHIPS ({{count}})</a>
</h4>
</div>
<div :id="items.id" class="panel-collapse collapse">
<div class="my-panel-body">
<div class="my-panel-body">
<div class="panel-group" :id="items.id" >
<div class="panel my-panel-warning" v-for="child1 in roles">
<div class="panel-heading">
<a data-toggle="collapse" :data-parent="'#'+items.id" :id="'child'+child1.id" :href="'#role'+child1.id" #click="getSpecialisation(child1.id, child1.name)">{{child1.name+" (0)"}}</a>
</div>
<div class="my-panel-body">
<div :id="'role'+child1.id" class="panel-collapse collapse">
<div class="panel my-panel-warning" v-if="child1.id === child2.parent_id" v-for="child2 in specialisations[child1.name]">
<div class="panel-heading">
<a data-toggle="collapse" :data-parent="'#role'+child1.id" :id="'child2'+child2.id" :href="'#spec'+child2.id" #click="getWithRoles(child2.id)">{{child2.name+" (0)"}}</a>
</div>
<div class="my-panel-body">
<div :id="'spec'+child2.id" class="panel-collapse collapse">
<div class="my-panel-body">
.
.
.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
And calling following function in my methods:
getSpecialisation(id, name) {
axios.get('specialisations?company_id='+this.company_id+'&role_id='+id, {headers: getHeader()}).then(response => {
if(response.status === 200)
{
this.specialisations[name] = response.data.specialisations
}
})
},
But some how I am unable to display the data. Previously I tried v-for="child2 in specialisations" and in response I did this.specialisations = response.data.specialisations I was getting all similar child element for all parents I know this is wrong but just wanted to inform that I was getting data and my accordion was displaying child elements, but once I did according to above method getSpecialisation mentioned, I am unable to display the data.
I can see my data in vue console:
Suggest me a better way for this.
Thanks
Instead of this.specialisations[name] = response.data.specialisations try:
Vue.set(this.specialisations, name, response.data.specialisations)
That should trigger Vue's change-detection.
Ps. When you see lots of nesting, this might be good time to split a big component up into smaller components.

Dynamically set class or id using index of ngFor loop

So I am trying to create a collapse (accordion) in Bootstrap 4 using Angular. I would love to be able to create almost the entire thing using an ngFor loop.
So far I have this:
<div class="row">
<div class="col-lg-6">
<div id="accordion" role="tablist" aria-multiselectable="true">
<div class="card" *ngFor="let environment of environments; let i = index;">
<div class="card-header" role="tab" id="headingi">
<h5 class="mb-0">
<a data-toggle="collapse" data-parent="#accordion" href="#collapsei" aria-expanded="false" aria-controls="collapsei">
Number: {{i}}
</a>
</h5>
</div>
<div id="collapseOne" class="collapse show" role="tabpanel" aria-labelledby="headingOne">
<div class="card-block">
<div *ngFor="let name of uniqueNames; let j = index" class="card infoBox">
<p>this is accordion {{i}}, section: {{j}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
What I am trying to do is use "let i = index" to set the id and class names needed to make the accordion know what to do when certain links are clicked. So ideally the first accordion section would have class and id of collapse0/heading0 and the next would have id and class of collapse1/heading1 etc.
However, the previous code must not be working because all the accordions and their headers show up and do nothing when clicked on. It does generate the correct number, show all the right headers, and the bodies associated with them.
Any help? thanks!
You can do it this way also
id="collapse{{i}}" class="heading{{i}}" attr.aria-controls="heading{{i}}"
and the fact that aria- attributes are being handled another way in angular you have to prefix them with attr.. In your example should that be attr.aria-controls="heading{{i}}".
You just have to databind id:
<div class="card-header" role="tab" [id]="'heading'+i">
<!-- and -->
<div [id]="'collapse' + i" class="collapse show" role="tabpanel" [aria-labelledby]="'heading' + i">
And then you can access your index via i.
*Here is working code with bootstrap 5 accordion with ngFor Angular 12 (dynamic id):
<div class="accordion" id="accordionPanelsStayOpenExample">
<div class="accordion-item">
<h2 class="accordion-header" id="panelsStayOpen-headingOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#panelsStayOpen-collapseOne" aria-expanded="true" aria-controls="panelsStayOpen-collapseOne">
Installed Offer Version Details
</button>
</h2>
<div id="panelsStayOpen-collapseOne" class="accordion-collapse collapse show" aria-labelledby="panelsStayOpen-headingOne">
<div class="accordion-body">
<ng-container *ngFor="let lineItem of allLineItems">
<!-- <line-item-detail [lineItem]="lineItem"></line-item-detail>-->
<div class="accordion-item my-4">
<h2 class="accordion-header" id="heading{{lineItem.id}}">
<button class="accordion-button" type="button" data-bs-toggle="collapse" attr.data-bs-target="#collapse{{lineItem.id}}" aria-expanded="true" attr.aria-controls="collapse{{lineItem.id}}">
{{lineItem.productType}} : {{lineItem?.productOffering?.name}}
</button>
</h2>
<div id="collapse{{lineItem.id}}" class="accordion-collapse collapse show" attr.aria-labelledby="heading{{lineItem.id}}">
<div class="accordion-body">
your body text
</div>
</div>
</div>
</ng-container>
</div>
</div>
</div>
</div>
Even you can create sub-component of what is in ngFor like I commented the <line-item-detail></line-item-detail> tag.

How to align cards in different rows

I'm trying to do something like this: https://nomadlist.com/
Rows of 3 elements (cards?) Going from top to bottom. Same size, perfectly aligned.
I'm using Handlebars and Bulma CSS, and the card components and doing this:
<div class="columns">
{{#each serverElements}}
<div class="column">
<div class="card">
<header class="card-header">
<p class="card-header-title">
{{this.title}}
</p>
<a class="card-header-icon">
<span class="icon">
<i class="fa fa-angle-down"></i>
</span>
</a>
</header>
<div class="card-content">
<div class="content">
{{this.body}}
<a>#bulmaio</a>. <a>#css</a> <a>#responsive</a>
<br>
<small>this.createdAt</small>
</div>
</div>
<footer class="card-footer">
<a class="card-footer-item">Save</a>
<a class="card-footer-item">Edit</a>
<a class="card-footer-item">Delete</a>
</footer>
</div>
</div>
{{/each}}
</div>
And it partially works. Each of the elements gets its own card. But this prints them all on the same row. And with different sizes.
If i understand you right, You sould use the is-multiline modifier with the right column, if you want 3 in a row, then use `column is-4'.

Jquery Target a tag in the third child of previous sibling

I'm not so great with traversing in jquery. Here is my markup:
<div class="row planarea">
<div class="col-md-6">
<h1>Agera Fixed Advantage 12</h1>
Fixed Price - 12 Months<br>
Utility: Con Edison
</div>
<div class="col-md-3">
<span class="price">$0.0799</span> <span class="killowats">/ kWh</span>
</div>
<div class="col-md-3">
<a class="nolink showmore" data-toggle="collapse" data-target="#24moscollapse" aria-expanded="false" aria-controls="24moscollapse">
<div class="selectdetails">
Details <i class="fa fa-chevron-circle-down" aria-hidden="true"></i>
</div>
</a>
<label >
<input type='radio' name="prefs" class="hidecheck" value="mail">
<span></span>
</label>
</div>
</div><!--row-->
<div class="row collapse detailsrow" id="24moscollapse">
<div class="col-xs-12 plandetailsbox">
stuff
</div>
</div>
what I want to do is something similar to this:
$('.detailsrow').on('show.bs.collapse', function () {
$(this).prev().closest().("a.showmore").html('<div class="selectdetails">Details <i class="fa fa-chevron-circle-up" aria- hidden="true"></i></div>');
})
I can't seem to figure out how to target that a tag and it's getting kind of confusing. I need to target what I believe is the a tag in the third child of the previous sibling for every repeated row of this information. Any help would be appreciated.
closest() finds the first parent. And closest(selector) finds the first selector matched parent.
Whereas, you are looking for a child. So, you can use find(selector).
Change this:
$(this).prev().closest().("a.showmore")
To this:
$(this).prev().find("a.showmore")

Manage complex select/deselect artis/album/song

First of all sorry for the vague title, but i didn’t know how to explain my problem in a better way.
Anyway this is what i want. Let’s say we have three tabs: one showing artist list, one showing album list and one showing songs. All this three tabs has selectable lists and i would like to be able, for example, to select and artist, then going to albums (that now should be show all as selected because i checked the artis) and be able to deselect one album and then, for, example, be able to go to songs and manage the songs individually.
Of course then i should be able to retrive the list of all the songs selected by the user.
EDIT 1
added two images to explain better
EDIT 2
Added some code. At the moment i have only HTML and CSS, i'm waiting for your help for the JS code :)
that's the HTML structure
<div id="tabs" class="page-content tabs overflowTab">
<div id="tab1" class="tab active">
<div class="content-block-title" id="indexScrollOffset">Seleziona artisti</div>
<div class="list-block media-list">
<ul>
<li>
<div class="item-content.modificato">
<div class="item-media modificato">
<i class="icon icon-form-checkbox modificato"></i>
</div>
<a href="#" class="item-link" id="apriTitoliLibro1">
<div class="item-inner modificato">
<div class="item-title-row">
<div class="item-title">Artist 1</div>
</div>
<div class="item-subtitle">Some Text</div>
</div>
</a>
</div>
</li>
<li>
<div class="item-content.modificato">
<div class="item-media modificato">
<i class="icon icon-form-checkbox modificato"></i>
</div>
<a href="#" class="item-link" id="apriTitoliLibro2">
<div class="item-inner modificato">
<div class="item-title-row">
<div class="item-title">Artist 2</div>
</div>
<div class="item-subtitle">Some Text</div>
</div>
</a>
</div>
</li>
[...]
</ul>
</div>
</div>
<div id="tab2" class="tab">
<div class="content-block-title">Seleziona Album</div>
<div class="list-block media list">
<div class="list-group">
<ul>
<li class="list-group-title">Artist 1</li>
<li id="titoliLibro1">
<div class="item-content-modificato titoli">
<div class="item-media modificato fake-media-list">
<i class="icon icon-form-checkbox modificato"></i>
</div>
<a href="personalizzaArticoli.html" class="item-link">
<div class="item-inner modificato titoli">
<div class="item-title-row modificato">
<div class="item-title modificato">Album 1</div>
<div class="item-after modificato"><span class="font-size-artt-label">Some text</div>
</div>
</div>
</a>
</div>
</li>
<li>
<div class="item-content-modificato titoli">
<div class="item-media modificato fake-media-list">
<i class="icon icon-form-checkbox modificato"></i>
</div>
<a href="personalizzaArticoli.html" class="item-link">
<div class="item-inner modificato titoli">
<div class="item-title-row modificato">
<div class="item-title modificato">Album 2</div>
<div class="item-after modificato"><span class="font-size-artt-label">Some text</div>
</div>
</div>
</a>
</div>
</li>
[...]
</ul>
</div>
</div>
</div>
<div id="tab3" class="tab">
<div class="content-block-title">Seleziona song</div>
<div class="list-block searchbar-not-found">
<ul>
<li class="item-content">
<div class="item-inner">
CONTENT HERE IS ADDED DYNAMICALLY FROM A WEBSQL DB
</div>
</li>
</ul>
</div>
</div>
Edit 3
It's a phonegap application and yes, already using jQuery (as less as possibile for performance) :)
Now my question: which is the best way to handle this? My only idea is to create an array and update it with all the elements selected and, in order to show an element as selected or not, checking it with indexOf to see if it exist… is this a good way? I’m a bit worried about performance.
Thanks

Categories