Disable one button in ngFor in Angular - javascript

I have an add to list button in my component, that disables when a user clicks it once. Problem is when the user clicks the button next to the list item they want to add, it disable all the other list buttons also? I only want it to disable the one selected. My code so far is:
component.html
<div *ngFor="let itunes of data | paginate: { itemsPerPage: 10, currentPage: p } | filter:filter; let i = index">
<div class="row">
<div class="col-lg-2 col-md-2 col-sm-12">
<img class="align-self-start mr-5 mb-5 artwork" src="{{itunes.artworkUrl100}}" alt="image">
</div>
<div class="col-md-8 col-lg-8 col-sm-12">
<h2 class="mt-0 d-inline-block text-truncate trunc">{{itunes.collectionName}}</h2>
<h4 class="mt-0 mb-3">{{itunes.artistName}}</h4>
<h5 class="mt-0 mb-3">Listen</h5>
</div>
<div class="col-md-2 mb-5 col-lg-2 col-sm-12">
<a target="_blank"><button type="button" class="btn btn-primary btn-lg float-right"
(click)="addSongToPlaylist(itunes); clicked = true;" [disabled]="clicked">
<fa-icon [icon]="faPlus">
</fa-icon>
</button></a>
</div>
</div>
</div>
component.ts (Add function)
addSongToPlaylist(itunes) {
this.list.playlist.push(Object.assign({}, itunes));
this.list.savePlaylist();
console.log('Playlist - ', this.list.playlist);
}
Any ideas, what I am doing wrong?

You have only one clicked property and all buttons have their disabled property bound to that property. That is why they are all enabled or disabled at the same time.
The simplest solution is to add a clicked property to the Itunes class, and modify its value when the button is clicked:
(click)="addSongToPlaylist(itunes); itunes.clicked = true;" [disabled]="itunes.clicked"
An alternative is to store the clicked value in a separate array, where each array item refers to an item of the data array.

Maybe do this:
<button type="button" class="btn btn-primary btn-lg float-right"
(click)="addSongToPlaylist(itunes); clicked = i;" [disabled]="clicked===i">
<fa-icon [icon]="faPlus">
</fa-icon>
</button>

Related

How do I add new row of data with javascript?

I'm creating add file function for my user, in this function, user have to insert their file name, choose their file then click on the Add Document button.
once user have add the document it will display back the user document under the add document button. User can add more as many as document they want.
I have trouble in adding the data. The file keep getting missing when user try to attach new file.
I want to display all file list of the user before the submitting it.
first add document
then user wants to add another document, the first document get replaced
second document
how do I make it not to overwrite the older document when user add more document ?
<div class="col-md-12 mb-3">
<textarea class="form-control" id="name" ></textarea>
</div>
<div class="col-md-12 mb-3">
<button type="button" class="btn btn-success w-100 choseDoc">Select document</button>
<input type="file" id="file" hidden>
</div>
<div class="col-md-12 mb-3">
<button type="button" class="btn btn-info w-100" onclick="myFunction()">Add Document</button>
</div>
<div>
<p id = "demo"></p>
</div>
<script>
function myFunction() {
let filename= $('#name').val();
let doc = $('#file').val();
let fileData = '';
fileData += `<div class="tab-content col-12 mt-4" id="myTabContent-2">
<div class="tab-pane fade show active" id="addCustodian" role="tabpanel" aria-labelledby="addCustodian-tab">
<div class="col-md-12">
<ul class="perfomer-lists m-0 p-0" id="">
<li class="d-flex mb-4 align-items-center">
<img class="avatar-20 rounded ml-2" src="assets\avatar.png" style="width: 50px;">
<div class="media-support-info ml-3">
<a class="font-size-12 font-weight-600"><b>${filename}</b></a>
<p class="mb-0 font-size-12"> ${doc}</p>
</div>
</li>
</ul>
</div>
</div>
</div> `;
document.getElementById("demo").innerHTML = fileData;
Besides the fact that your approach brings some pitifals in performance you have a little logical mistake
<div class="col-md-12 mb-3">
<textarea class="form-control" id="name" ></textarea>
</div>
<div class="col-md-12 mb-3">
<button type="button" class="btn btn-success w-100 choseDoc">Select document</button>
<input type="file" id="file" hidden>
</div>
<div class="col-md-12 mb-3">
<button type="button" class="btn btn-info w-100" onclick="myFunction()">Add Document</button>
</div>
<div>
<p id = "demo"></p>
</div>
<script>
let fileData = ''; // <--- must be declared outside your function to keep the state
function myFunction() {
let filename= $('#name').val();
let doc = $('#file').val();
fileData += `<div class="tab-content col-12 mt-4" id="myTabContent-2">
<div class="tab-pane fade show active" id="addCustodian" role="tabpanel" aria-labelledby="addCustodian-tab">
<div class="col-md-12">
<ul class="perfomer-lists m-0 p-0" id="">
<li class="d-flex mb-4 align-items-center">
<img class="avatar-20 rounded ml-2" src="assets\avatar.png" style="width: 50px;">
<div class="media-support-info ml-3">
<a class="font-size-12 font-weight-600"><b>${filename}</b></a>
<p class="mb-0 font-size-12"> ${doc}</p>
</div>
</li>
</ul>
</div>
</div>
</div> `;
document.getElementById("demo").innerHTML = fileData;

How to make the clickable buttons for start and stop for particular buttons from the loop of buttons

I have created the clickable buttons dynamically from the data(i.e based on the backend da ta number of buttons will come).
But the problem is while clicking on any button from start to stop, all the remaining buttons also changed to stop.
.component.ts
public isCollapsed = false;
toggleCollapse() {
this.isCollapsed = !this.isCollapsed
}
.component.html
<ul class="list-group" >
<li class="list-group-item" *ngFor="let y of data">
<div class="">
<div class="row no-gutters">
<div class="col-sm-5">
<h5>{{y.d1}}</h5>
<h6>Latitude: {{y.d2}}</h6>
<h6 class="card-text "> Longitude: {{y.d3}}</h6>
</div>
<div class="col-sm-4">
</div>
<div class="col-sm-3">
<button type="button" [ngClass]="isCollapsed ? 'btn btn-success btn-sm' : 'btn btn-danger btn-sm'" (click)="toggleCollapse()">
<span *ngIf="isCollapsed"> START </span>
<span *ngIf="!isCollapsed"> STOP</span>
</button>
</div>
</div>
</div>
</li>
</ul>

Javascript - make html/bootstrap button active by function

I have a button group that on click gets background color of blue:
<div class="btn-group-vertical answers_group" data-toggle="buttons-radio">
<button button type="button" onclick="setArrayAnswer('optionA')" id="optionA" class="text-left btn text-secondary border border-info" data-toggle="button">
<h3 class="text-primary">A.</h3>
<p id="optionA_text" class="text-secondary text-left"></p>
</button>
<button button type="button" onclick="setArrayAnswer('optionB')" id="optionB" class="text-left btn text-secondary border border-info" data-toggle="button">
<h3 class="text-primary">B.</h3>
<p id="optionB_text" class="text-secondary text-left"></p>
</button>
<button button type="button" onclick="setArrayAnswer('optionC')" id="optionC" class="text-left btn text-secondary border border-info" data-toggle="tab">
<h3 class="text-primary">C.</h3>
<p id="optionC_text" class="text-secondary text-left"></p>
</button>
<button button type="button" onclick="setArrayAnswer('optionD')" id="optionD" class="text-left btn text-secondary border border-info" data-toggle="button">
<h3 class="text-primary">D.</h3>
<p id="optionD_text" class="text-secondary text-left"></p>
</button>
</div>
Now when the user click a button i store in an array a status of which answer he chose above. What i try to achieve is when a question gets loaded if it has already been answered i want to have the same effect as when i click it which i achieve like this:
.btn:focus {
background: #81d4fa;
}
I tried with the following JS code:
var answer_id = "option" + subject1_arr[subject1_question].answer;
document.getElementById(answer_id).click();
Basically i just try to click the item depending on the ID which i get by concatenating the base id for all and adding the appropriate letter, but it doesn't work.

How to prevent Elements BENEATH a Bootstrap Multiselect dropdown from firing on click of multiselect?

When a user clicks an option in a Bootstrap Multiselect dropdown a Bootstrap Toggle (http://www.bootstraptoggle.com/) Element BELOW is fired.
I'm not sure if this problem is specific to Bootstrap Multiselect and/or Bootstrap Toggle, or the interplay of the two - it is the only Element in my app that overlaps/hides other Elements.
The plugin works great...it's just that when you click Algebra (1 below) or really any option in the dropdown, the Bootstrap Toggles below (2 in the screenshot) are fired as if you clicked them directly.
How do I prevent this without a check-to-see-if-the-multiselect-is-open logic?
Adding HTML to address question...the divs were inside a single parent div and I moved them to be in separate Divs...same result: clicking the dropdown multiselect fires the listener on wordPref class.
<div class="row paddingMenu">
<div class='col-xs-12 alignleft'>
<b>Select</b> from <i>active</i> Libraries<a data-toggle="tooltip" data-placement="bottom" title="Click EDIT then ACTIVATE LIBRARIES to add and remove Libraries." tabindex="-1" class="pull-right"><span class="glyphicon glyphicon-info-sign pull-right" style="font-size: 15px"></span></a>:
</div>
<div class='col-xs-12 aligncenter'>
<div class='form-group'><select id='ddLibName' multiple='multiple'></select>
<div id='ddLibrarySelect'></div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 aligncenter" data-toggle="tooltip" data-placement="bottom" title="Choose whether to insert selected Comments as Word comment bubbles OR inline text.">
<input type="checkbox" id="insertMode" class="wordPref" data-toggle="toggle" data-size="small"
data-off="Inline" data-on="Comment"
data-offstyle="info" data-onstyle="success">
</div>
<div class="col-xs-4 aligncenter" data-toggle="tooltip" data-placement="bottom" title="Save document owner/author info with your usage statistics. This setting may be defined by your institution.">
<input type="checkbox" id="logMode" class="wordPref" data-toggle="toggle" data-size="small"
data-off="History OFF" data-on="History ON"
data-offstyle="info" data-onstyle="success">
</div>
<div class="col-xs-4 aligncenter">
<a class="btn btn-primary btn-sm" id="refreshBtn" data-toggle="tooltip" data-placement="bottom" title="Refresh AP to pull down any content changes or purchases." tabindex="-1">Refresh</a>
</div>
<div id='upsellMsgDiv' class='apSidebarAlert col-xs-12 hide'>
<div class="spacer-5"></div>
<div class="panel panel-warning">
<div class="panel-body highlight-cell">
<span class="apAlertMsg"></span>
<div id='closeAlertBtn' class='col-xs-12 spacer-5 hide'>
<button class='btn-sm btn-primary closeSidebarAlert pull-right' type='button'>Close</button>
</div>
</div>
</div>
</div>
</div>
I haven't used it but are those two inside a same div? Is one of them is a parent?.. Share your code as well... You can try doing
e.stopPropagation()
to the below div if the dropdown div is the parent div.

How can I choose a sub document to insert and update with a click function from the client side

I have two collections, one is a Posts collection which has posts, with an id.
And the other is a Sets collection which has an array called ArticleId that can be updated by the user by inserting a post id from the Posts collection into it via a click function with the button toggle-addToSet.
The user Creates the Array called ArticleId, gives it a name and saves articles in it periodically. Think Pinterest Boards or G+ collections.
I have a button on the post item that when a user clicks the icon, all the Sets he has created come up in a dialogue and the user chooses which Set he want to save the post id into.
<template name="summeryArticle">
<li>
<div class="row col s12 m7">
<div class="card" id="cardId">
<div class="card-image waves-effect waves-block waves-light">
<img src="{{better_featured_image.source_url}}">
</div>
<div class="card-content">
<h5 class=" truncate grey-text text-darken-4">{{title.rendered}}</h5>
MORE <i class="waves-effect waves-teal small material-icons right">playlist_add</i>{{>
likePartial}}{{> reblogPartial}}
<!-- The modal below is what brings up all the sets the user has created so that the user can pick with set they wat to save the article in -->
<div id="modal2" class="modal bottom-sheet">
<div class="modal-content">
<div class="row">
{{#each set}}
<div class="col s6 m6 addSet teal">
<div class="card ">
<div class="card-image">
<span class="card-title cardSet">{{name}}</span>
</div>
<div class="card-footer">
<button type="button" class="btn toggle-addToSet" name="button">add Article Id to this Set!</button>
</div>
</div>
</div>
{{/each}}
</div>
</div>
</div>
</div>
</div>
</div>
</li>
</template>
Graphically it looks like this
And when the user clicks the icon modal-trigger to bring up the Sets he created, it looks like this
As you can see, the user has three Sets, Lifestyle, Love, Business, they can choose to save the posts id into any one of those three.
## GOAL ##
I want to be able to choose a Set, click the add button of my chosen Set, and somehow capture the post Id of the current post in my foreach loop, and insert it into that via the click function, at the moment all I have is this
Template.summeryArticle.events({
'click .toggle-addToSet': function(e, template) {
var ob = this.id
console.log(ob);
}
});
and when I console log that, I just get the Set id instead of the post id.
Question
How can I capture the post id of the current post,
Choose a Set of my liking, then insert the post id into my chosen set?
And if there is a better way to achieve this, please let me know.
EDIT AFTER FEEDBACK
I did the second option like this
<template name="summeryArticle">
{{#let article=this}}
<li>
<div class="row col s12 m7">
<div class="card" id="cardId">
<div class="card-image waves-effect waves-block waves-light">
<img src="{{better_featured_image.source_url}}">
</div>
<div class="card-content">
<h5 class=" truncate grey-text text-darken-4">{{title.rendered}}</h5>
MORE <i class="waves-effect waves-teal small material-icons right">playlist_add</i>{{>
likePartial}}{{> reblogPartial}}
<!-- The modal below is what brings up all the sets the user has created so that the user can pick with set they wat to save the article in -->
<div id="modal2" class="modal bottom-sheet">
<div class="modal-content">
<div class="row">
{{#each set}}
<div class="col s6 m6 addSet teal">
<div class="card ">
<div class="card-image">
<span class="card-title cardSet">{{name}}</span>
</div>
<div class="card-footer">
{{#each s in set}}
<button type="button" class="btn toggle-addToSet" name="button" data-setid="{{s._id}}" articleid="{{article._id}}">add Article Id to this Set!</button> {{/each}}
</div>
</div>
</div>
{{/each}}
</div>
</div>
</div>
</div>
</div>
</div>
</li>
{{/let}}
</template>
my helper is like this
Template.summeryArticle.events({
'click .toggle-addToSet': function(e, template) {
var ob = this
console.log(ob);
var sid = $(e.currentTarget).data('setid');
var aid = $(e.currentTarget).data('articleid');
console.log(sid);
console.log(aid);
}
});
However, this is what I'm getting.
and the log looks like this
where 7MgLCEnTWjXFRhLg6 is the Sets_id depending on which of the three buttons I clicked
SECOND EDIT. CONTEXT
when i do this
<template name="summeryArticle">
{{#let article=_id}}
<li>
<div class="row col s12 m7">
<div class="card" id="cardId">
<div class="card-image waves-effect waves-block waves-light">
<img src="{{better_featured_image.source_url}}">
</div>
<div class="card-content">
<h5 class=" truncate grey-text text-darken-4">{{title.rendered}}</h5>
MORE <i class="waves-effect waves-teal small material-icons right">playlist_add</i>{{> likePartial}}{{> reblogPartial}}
<!-- The modal below is what brings up all the sets the user has created so that the user can pick with set they wat to save the article in -->
<div id="modal2" class="modal bottom-sheet">
<div class="modal-content">
<div class="row">
{{#each s in set}}
<div class="col s6 m6 addSet teal">
<div class="card ">
<div class="card-image">
<span class="card-title cardSet">{{name}}</span>
</div>
<div class="card-footer">
<button type="button" class="btn toggle-addToSet" name="button" data-setid="{{s._id}}" articleid="{{article._id}}">add Article Id to this Set!</button>
</div>
</div>
</div>
{{/each}}
</div>
</div>
</div>
</div>
</div>
</div>
</li>
{{/let}}
</template>
I get this
What's going on here is that I have the articles organised in categories, so what's going on now is that the article=_idbeing captured is the last article in the category, no matter what articles I try to add, it's just one article being caught, and its always the one at the bottom. I have no idea why
There are several ways. One would be something like this:
I would but article id and set id to toggle-addToSet button's data-attributes:
<button type="button" class="btn toggle-addToSet" name="button" data-setid="SETID" data-articleid="ARTID">add Article Id to this Set!</button>
If you call your summeryArticle like this:
{{#each article in articles}}
{{>summeryArticle article=article}}
{{/each}}
(another opotion is use let-helper:
<template name="summeryArticle">
{{#let article=this}}
...
{{/let}}
</template>
Then in your summeryArticle-template you can get article id in sets-loop:
{{#each s in set}}
<button type="button" class="btn toggle-addToSet" name="button" data-setid="{{s._id}}" articleid="{{article._id}}>add Article Id to this Set!</button>
{{/each}}
Then in template events:
Template.summeryArticle.events({
'click .toggle-addToSet': function(e, template) {
var ob = this.id
console.log(ob);
var sid = $(e.currentTarget).data('setid');
var aid = $(e.currentTarget).data('articleid');
Sets.update({_id: sid}, {$addToSet: {ArticlesId: aid}});
}
});
Note!
This assumes you can update your collection directly from client side! Depending on your situation, but usually it is not recommended. Normally you should deny client side updates and use methods for updating collections:
Method.call('mymethd', sid, aid, function(e, r) {
if (!e) {
console.log(r);
} else {
console.error(e);
}
});

Categories

Resources