I want to implement a function to hide elements when button is clicked in an application built using Angular 2.
<div *ngFor="let todo of todos" class="col-sm-8 col-sm-offset-2">
<div class="panel panel-default step"> // from here
<div class="panel-body">
<a [routerLink]="['/todo', todo.id]">{{todo.title}}</a>
<button (click)="delete(todo.id)" type="button" class="btn btn-success btn-circle pull-right"><i class="glyphicon glyphicon-ok"></i></button>
</div>
</div>//so far
</div>
I want to know how to make the todo disappear when the button is clicked with the above code.
Although it is an elementary question, please teach.
You should be removing that todo item as below
delete(id:number){
this.todos.splice(id,1)
}
Small changes to Aravinds answer, since we need to find the index of the todo, so that right todo will be deleted
I like to pass the object in delete:
(click)="delete(todo)"
Need to find the index of the todo and then splice.
delete(todo) {
this.todos.splice(this.todos.indexOf(todo),1);
}
Update:
Just realized that it seems that you only want to hide the todo, and not delete it entirely. Well this can be achieved with the following. Upon initialization all todo's are visible. We could introduce a new variable to todo, when we want to hide it. So initially this property doesn't exist, so we mark inside the iteration: *ngIf="!todo.hidden", complete code:
<div *ngFor="let todo of todos">
<div class="panel-body" *ngIf="!todo.hidden">{{todo.name}}
<button (click)="hide(todo)" type="button">Hide Todo</button>
</div>
</div>
And the hide function sets the hidden property as true:
hide(todo) {
todo.hidden = true;
}
This doesn't obviously give the option to actually unhide the todo, but that was not mentioned in your question.
I think this is not the right way to 'remove' an element on a todo list. #Aravind answer is better for it.
But if you really want to use display:none, you can do this like :
https://plnkr.co/edit/eXwAWWeH9N6REsqpzFCq?p=preview
<element ng-style="displayStyle"></element>
<button value="displayNone" ng-click="displayStyle={'display':'none'}">Display none</button>
Related
So basically, I have a vue web app and created a container with multiple bootstrap cards. The cards have a button, which collapses a form I've made for guests to apply. However, when I press the button of a card, it collapses the apply form of all cards at once. To fix that, I have to give each individual card a specific id which matches the data-bs-target and aria-controls of the button. So far, so good.
I've made a variable card_id and inserted it into the attribute values with v-bind, but it's not working. The reason is, that the attribute data-bs-target needs a hashtag before the actual variable name, but I can't figure out a way to do that.
Code sample:
<button class="btn btn-primary" type="button" data-bs-toggle="collapse" :data-bs-target="card_id" aria-expanded="false" :aria-controls="card_id">Apply now!</button>
<div class="collapse" :id="card_id">
<div class="card card-body">
<GuestForm></GuestForm>
</div>
</div>
I obviously can't just put a hashtag in front of the variable, so what is my next best solution for this?
Thank you in advance.
You could use the string template with backticks `` like:
<button :data-bs-target="`#${card_id}`"
So, I'm trying to use a angular way to send the buttons created to either the #start or #finish divs, based on click on the buttons selected, so in a way they would send themselves if you may if they follow a condition, which in this case is to be either inside of the #start or #finish divs. With Jquery, I just check what's the parent of certain element, if matches one, I send it to the other, and vice versa. Now with angular, I have been looking into the whole, rendering and stuff, but my head can't just understand the overall picture, and I even though I was able to click and send the element clicked to a different div, I couldn't do it with the other buttons created, and also with the button that was first clicked, in the other div.
<div class="ui raised very padded text container segment"
#finish>
</div>
<div class="ui raised very padded text container segment" #start>
<button
*ngFor='let word of ge_array'
(click)="goToNext()"
>{{word}}</button>
</div>
Does anybody know how to tackle this situation?
Renan, I would change all your plan. I have an array of element. this elements have a property "place". I will show in two div one for "plan1" and the other for "plan2".
//the .ts is like
items:any[]=[{word:'uno',place:1},{word:'dos',place:1},{word:'tres',place:2}]
get items1(){
return this.items.filter(it=>it.place==1);
}
get items2(){
return this.items.filter(it=>it.place==2);
}
//the .hmtl like
<h2>place 1</h2>
<button *ngFor="let item of items1" (click)="item.place=2">{{item.word}}</button>
<h2>place 2</h2>
<button *ngFor="let item of items2" (click)="item.place=1">{{item.word}}</button>
I would prefer using a getter and have "item1" and "item2". the click make that the property "place" of the item becomes 2 in place 1 and becomes 1 in place2
You can make two *ngFor over the same array also using a *ngIf like
<h1>place 1</h1>
<div *ngFor="let item of items">
<button *ngIf="item.place==1" (click)="item.place=2">{{item.word}}</button>
</div>
<h1>place 2</h1>
<div *ngFor="let item of items">
<button *ngIf="item.place==2" (click)="item.place=1">{{item.word}}</button>
</div>
and forget the getters
I want to get the previous input id from the button (point of view).
With the needs of my website, there will be at least 8 inputs like this and buttons of course.
So in order to facilite the task and avoid writing one function by input, I think this is way better to get the id of the 'previous' input from the button where I click.
I've browsed StackOverflow, but found nothing interesting in my case.
So here is the HTML code :
<div class="col-sm-3">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" ><i class="fas fa-link"></i></span>
</div>
<input type="text" name="first_map_link" class="form-control" id="first_map_link" placeholder="Lien première map...">
</div>
</div>
<div class="row">
<div class="col-sm-1">
<button class="btn btn-outline-info btn-get-infos"><i class="fas fa-search"></i></button>
</div>
</div>
I've tried with that : Undefined
$('.btn-get-infos').closest('input').attr('id')
Same with siblings. jQuery solution is prefered.
Thanks in advance
The issue is because closest() goes up the DOM looking for parent elements, while the input you want to find is a child of a sibling to a parent of the button you click on. With that in mind you'll need a combination of closest(), prev() and find(), like this:
var id = $('.btn-get-infos').closest('.row').prev('.col-sm-3').find('input').prop('id')
You'll need to walk up and down the DOM properly to find reference. Something like this:
$('.btn-get-infos').prev().find('input').attr('id');
Or if you're firing a click event, it can use the this keyword:
$this = $(this); //ref to the button clicked
$this.prev().('input').attr('id');
Give that a go and let us know if it works, dude. attr() i think was deprecated a while back, so new practise is to use prop().
Edit: I realise now that prev() only looks through previous siblings - ignore me :)
I have a loop that generates let's say 20 divs. Each div is an object from my local objects array. Here's the code:
<div *ngFor="let item of userInventory"
class="col-2 c-pointer"
(click)="addItemToArray(item)">
<img src="{{item.image}}" class="img-fluid"/>
<span class="d-block">{{item.name}}</span>
</div>
When a user clicks on the div(item) it will add the item to an array:
addItemToArray(item) {
this.itemsToSend.push(item);
item.isAdded = true;
}
The user under no circumstances is allowed to add the same item twice in the array, but I do not want to mutate the userInventory array (or splice() it). I want it to still be visible, just change some styles on it so it looks disabled. Also as you can see, when the item is clicked, item.isAdded becomes true.
What I want to do is, when item.isAdded is true, disable the (click) event listener on the div (and add some styles), so that the user cannot add the same item twice, despite clicking on it multiple times.
Is this doable in the current Angular implementation?
try it with a condition:
(click)="!item.isAdded && addItemToArray(item)"
For that, you can add a class for each items which are added in the cart as below:
<div *ngFor="let item of userInventory"
class="col-2 c-pointer"
[class.disabled]="item.isAdded" <!-- Add this class, and customize its look -->
(click)="addItemToArray(item)">
<img src="{{item.image}}" class="img-fluid"/>
<span class="d-block">{{item.name}}</span>
</div>
Then, in your .ts component file, add this condition:
addItemToArray(item) {
if (!item.isAdded) {
this.itemsToSend.push(item);
item.isAdded = true;
} else {
// add some error flash message
}
}
Hope it helps! :)
For the class, you can use this :
<div *ngFor="let item of userInventory" [class.disabled]="item.isAdded">
(I removed attributes for the sake of readability)
For the click, you can use a ternary :
<div *ngFor="let item of userInventory" (click)="item.isAdded ? null : addItemToArray(item)">
But the best solution would simply be to use a condition in your click handler I think.
You can simply use disabled property to achieve this:
<div *ngFor="let item of userInventory"
class="col-2 c-pointer"
(click)="addItemToArray(item)"
[attr.disabled]="item.isAdded">
<img src="{{item.image}}" class="img-fluid"/>
<span class="d-block">{{item.name}}</span>
</div>
Rather new to javascript, jquery and bootstrap, etc., so bear with me. I have a situation where I want to present a list of errors in a model dialog after the user hits a "validate" button. Got all the working - I am generating a list of objects that indicate to the user they need more work to the exact spot that needs additional data entry. I have the the DIV "id" that represents the field that needs more data (and each item will jump someplace different).I do not want a drop down list since there are be lots and lots of these items.
A few questions:
How do I go about jumping from the modal to the main html. I believe I have seen scrollIntoView mentioned in a few other posts as I was looking but will that hop to the DIV and also close the modal?
What construct should I use for the list? A list of scrolling button? The size of this can be quite large (hundreds) so it will need a scroll capability.
Finally, the app is "paged" with a next and prev buttons. I assume that will not be a problem from the aspect of jumping to a page not already displayed?
Here is the current modal code:
<script id="template-validation-error" type="text/x-handlebars-template">
<div id="validationErrorModal" class="modal">
<div class="message-container">
<div class="header">
Validation Errors
</div>
<div class="message">
The following fields are required:
</div>
<div class="center">
<input type="button" class="btn btn-solid-green btn-sm" onclick="fffdevice.validationErrorOk();" value="Done" />
</div>
</div>
</div>
</script>
and
showValidationError: function (fieldlist) {
settings.focusedField = $(':focus');
$("#validationErrorModal").detach();
$(".device-container").append(templates.validationerror({ fieldlist }));
$(".message-container input").focus();
},
validationErrorOk: function () {
$("#validationErrorModal").detach();
if (settings.focusedField) {
settings.focusedField.focus();
}
},
The field list is a list of objects that contain the id (field.id) of the DIV and also a description (field.fieldName) that I want to display.
Here is something I mocked up in paint...I am not sold on it but it show in a general sense what I am looking for:
I don't need a full solution rather, just want mechanisms I can use.
UPDATE
Just to help out anyone else in the future, using the info provided in the correct answer below I have a new code as follows:
<script id="template-validation-error" type="text/x-handlebars-template">
<div id="validationErrorModal" class="modal">
<div class="validation-container">
<div class="header" align="center">
Validation Errors
</div>
<div class="message">
<div class="scrolling-container" style="background-color: rgb(238, 238, 238); height:660px">
<div class="grid grid-pad">
{{#each fieldlist}}
<div class="row click-row" onclick="fffdevice.validationErrorFix('{{id}}');">
<div class="col-7-8 field-name">{{fieldName}}</div>
<div class="col-1-8">
<img class="pull-right" src="/mysite/Content/device/images/fix.png" style="width: 40px; position:relative; top: -5px;">
</div>
</div>
{{/each}}
</div>
</div>
</div>
<div><br/></div>
<div class="center">
<input type="button" class="btn btn-solid-green btn-sm" onclick="fffdevice.validationErrorOk();" value="Done" />
</div>
</div>
</div>
Then the Javascript for the onClick is:
validationErrorFix: function (id) {
$("#validationErrorModal").detach();
var x = document.getElementById(id);
x.scrollIntoView({
behavior: "smooth", // or "auto" or "instant"
block: "start" // or "end"
});
},
Which closes the dialog and jumps to the field. It looks like (I know this is ugly and I will clean it up later):
Bind the modal event to the validation code and show the modal if error(s) are found.
Display the modal with the list of errors using an html unordered list, inside the li element an anchor tag where the href attribute will have a value with the id that corresponds to the input field, all this done dynamically from your validation code.
Once an error in the list is clicked hide the modal using bootstrap $('#your-error-modal').modal('hide'); so the code would be something like this:
$('#your-error-modal').on('click', 'a.error-item', function(){
$('#your-error-modal').modal('hide');
});
I haven't tested this code, but if you're having issues with scrolling to the section of the input and closing the modal you can probably do something like this too:
$('#your-error-modal').on('click', 'a.error-item', function(e){ // use this method of onclick because your list will be created dynamically
e.preventDefault(); // prevent the default anchor tag action
var href = $(this).attr('href'); // grab the href value
$('#your-error-modal').modal('hide'); // close the modal first
scrollToDiv(href); // then take the user to the div with error with a nice smooth scroll animation
});
function scrollToDiv(location) {
$('html, body').animate({
scrollTop: $(location).offset().top
}, 2000);
}
Again this is untested code, but the idea is there.
For UX reasons you might also want to create a floating div or something where users can click on it and go back to the modal to continue reading your list of errors.