How to control multiple (click) events inside a table? - html

Hello I hope the title is descriptive enough to understand my problem,
I have this HTML code. In <td> i have attached a (click) function. Inside this <td>, I have another div which also has a (click) function attached. When I click the button inside <td> both functions are triggered.
But, I would like only the (click) in div to be triggered when I click it and not the <td> (click).
Is it possible to happen?
<td mat-cell align="center" *ngFor="let option of options; let opt_indx = index"
(click)="optionsClicked(opt_indx, i);" id="defaultBadge-wrapper">
<div *ngIf="!rowCommands[i].defaultSelected[opt_indx]" class="defaultBadge">
<a class="badge badge-secondary" matTooltip="Click here to set this Option as Default"
(click)="markDefault(i,option.id)">Default</a>
</div>
</td>
Typescript code
markDefault(index, option: string) {
alert('this function triggered');
}
optionsClicked(option, rule) {
alert('I dont want this function to be triggered when i click markDefault');
}

In ts method pass the $event as param and include
event.stopPropagation();
or in the click event pass another function:
(click)="markDefault(i,option.id); event.stopPropagation();">Default</a>

use the stoppropagation to prevent the event from propagating
(click)="markDefault(i,option.id); event.stopPropagation();">Default</a>

just add $event.stopPropagation() to inner click.
<div *ngIf="!rowCommands[i].defaultSelected[opt_indx]" class="defaultBadge">
<a class="badge badge-secondary" matTooltip="Click here to set this Option as Default"
(click)="$event.stopPropagation();markDefault(i,option.id)">Default</a>
</div>

Related

unwanted trigger of function in tr tag when clicking a button in row

i have a table with a button on each row.
<tbody>
<tr *ngFor="let user of users" (click)="accountDetails(user._id)">
<td>{{user.firstName | titlecase}} {{user.lastName | titlecase}}</td>
<td>{{user.email}}</td>
<td>{{user.mobile}}</td>
<td">
<button type="button" class="btn btn-primary"
(click)="blockUnblock(user._id, 1)">UnBlock</button>
</td>
</tr>
</tbody>
Here i have a click function in tag and one also in tag button.
I require to click on the row to execute accountDetails(), but on clicking the button also, the accountDetails() gets triggered alongwith blockUnblock().
how can i make the accountDetails() work, in rest of the row except on the button click
You can prevent propagation of the click event on parents by using Event.stopPropagation()
You can inline this method in your html in Angular:
(click)="blockUnblock(user._id, 1); $event.stopPropagation()"
^^^^^^^^^^^^^^^^^^^^^^^

Prevent expand on click on prime ng accordion

I have an primeng accordion and the accordion header has a checkbox control . Whenever i check/uncheck checkbox , the accordion tab is getting open/closed automatically
Is there any way to prevent expand/collapse on click on checkbox ? It should expand/collapse on header other than check/uncheck check box ?
This is happening due to Event Bubbling. For this need to stop eventPropagation by calling stopPropagation() of MouseEvent.
Accordion html code sample
<p-accordion>
<p-accordionTab header="Godfather I" [selected]="true">
<p-header>
<span>Godfather I
<input type="checkbox" (click)="onClick($event)">
</span>
</p-header>
Some Text
</p-accordionTab>
</p-accordion>
Corresponding component ts code.
onClick($event: MouseEvent){
$event.stopPropagation();
}
For Reference added stackblitz code sample.
This is how I solved this issue. This is happening because of Event Bubbling. So when you click on child element. Event propagate to its parent and so on. So Just use stop propagation on event. It will prevent the click event on your accordion. Below code for your reference.
Accordian with Check box code I used (onChange) method.
<p-accordionTab>
<p-header>
<div class="ui-g" style="width:250px;margin-bottom:10px">
<div class="ui-g-12"><p-checkbox name="group1" #ck value="New York" label="New York" [(ngModel)]="selectedCities" (onChange)="checkChange($event)" inputId="ny"></p-checkbox></div>
</div>
</p-header>
</p-accordionTab>
component.ts
selectedCities: string[] = [];
//Simply you have to to stop propogation here.
checkChange(e:any){
console.log(e); // true or false.
event.stopPropagation(); // component will have direct access to event here.
}

icon inside button does not trigger attached function on React

I am building app on React. I have a table of item list and have difficult invoking function on icon.
deleteItem = event => {
this.props.deleteRecord(event);
};
const RecordList = records.map(({ category, task, duration, id }, i) => (
<tr className="record-item" key={i} id={id}>
<td>
<span className="recordItem">{category}</span>
</td>
<td>
<span>{task}</span>
</td>
<td className="time-trashIcon-container">
<span>{duration}</span>
<button
type="button"
className="trashIcon"
id={id}
onClick={this.deleteItem}
>
<i className="far fa-trash-alt" />
</button>
</td>
</tr>
));
What I want to achieve
when user clicks the trash button (icon inside button tag), it calls a function to delete item.
Problem
For now, only when I click button padding, not icon itself triggers delete function. Clicking icon does not trigger anything.
What I tried
I wrap the icon inside span and tried giving delete function as onClick eventListener. It would trigger a function but it fails to find property I want to pass id of each item which I need to delete the target item.
I don't want to use jQuery. I have tried data-x to pass property and did not work either. Any help would be appreciated.
Thank you tons in advance.
Put it inside button. using below syntax you need not to bind if you are using ES6
onClick={e => this.deleteItem(id, e)}
write your delete code inside.
deleteItem(id, event) {
//TO-DO delete code
}
Instead of using button you can use <a>
<a className="trashIcon"
id={id}
onClick={e => this.deleteItem(id, e)}/> <i className="far fa-trash-alt"/></a>
Answering my own question for anyone who might have a similar problem :)
After trying a few things out below...
<a id={id} onClick={this.delete}>
<button id={id} onClick={this.delete}><a id={id} onClick={this.delete}><i className='trashIcon'></a></button>
<button id={id} onClick={this.delete}><span id={id} onClick={this.delete}><i className='trashIcon'></span></button>
All of them invoke delete function when clicking padding of icon, not the icon itself.
The working code was just to put <span><i/><span>

what is the method(way) to use data of html in component of angular 2?

in angular 2 there is a button that I want when click on it a div appear.
<button class="dokme" type="button" (click)="onSelect(signUp)" >Register</button>
<div *ngIf="selectedBtn">
<div>Hello</div>
</div>
and I couldn't complete my component, because I don't know how I should write it:
onSelect():void{
this.selectedBtn=...(?)}
Actually I know it can be similat to "Hide the empty detail with ngIf" in angular tutorial Hide the empty detail with ngIf, but the problem is I can't change that code to what I want. Because in that example there is hero and I don't know what should I replace it.
please help me in the simplest way it would be your kind.
The expression you pas into (click) will be executed when you click on the button.
If the expression you pass into *ngIf is true, the content inside the element will be present on the page. Otherwise, it will not.
So, what you ned to do is to change the value of selectedBtn when (click) event happens.
Template
<button class="dokme" type="button" (click)="onSelect()" >Register</button>
<div *ngIf="selectedBtn">
<div>Hello</div>
</div>
Component
onSelect() {
this.selectedBtn = true
}
Just set the variable to true
onSelect() {
this.selectedBtn = true;
}
ngIf works in a simmilar way that if statement in other programming languages so it checks for condition and if it is true (or if a function called in condition returns true). In this case, your ngIf is linked to component variable selectedBtn so only what you need to do is set it to true:
this.selectedBtn = true;
More easily, you can achieve the sane goal without creating new function in your controller.
<button class="dokme" type="button" (click)="selectedBtn=true" >Register</button>
<div *ngIf="selectedBtn">
<div>Hello</div>
</div>
Or if you want the button to toggle :
<button class="dokme" type="button" (click)="selectedBtn=!selectedBtn" >Register</button>
<div *ngIf="selectedBtn">
<div>Hello</div>
</div>

AngularJS change attribute values

I have rows in table which generate buttons dynamically
<tr ng-repeat="task in task">
<td>{{task.Name}}</td>
<td>{{task.Comments}}</td>
<td>{{task.Project}}</td>
<td>{{task.Duration}}</td>
<td>
<button class={{editable}} ng-click="editTask(task.id)"></button>
<button class="glyphicon glyphicon-trash"></button>
</td>
</tr>
In my Angular code I have
$scope.editTask = function(id){
if($scope.editable == "glyphicon glyphicon-edit"){
$scope.editable="glyphicon glyphicon-floppy-save";
}
else{
$scope.editable="glyphicon glyphicon-edit"
}
}
So basically I want to change the edit glyphicon to save glyphicon and the save glyphicon back to edit glyphicon. But since I have assigned class to the button it changes the glyphicons of all buttons in the table. How can I change the icon of only the button of which is clicked?
By assigning the editable variable to the task object:
$scope.editTask = function(task){
if(task.editable == "glyphicon glyphicon-trash")
task.editable="glyphicon glyphicon-floppy-save";
else
task.editable="glyphicon glyphicon-trash";
}
and in your HTML:
<button ng-class="editable" ng-click="editTask(task)"></button>
This way, you'll end up having an unique class for each of your task object.
Also, remember to use ng-class instead of the plain class attribute.
Approach 1
You can update your HTML to
<td>
<button class="glyphicon" ng-class="task.editable" ng-click="editTask(task)"></button>
<button class="glyphicon glyphicon-trash"></button>
</td>
Passing the task instead of the id directly allows you to update it's editable state directly on the task. Your controller should update the editable property
$scope.editTask = function(task){
if(task.editable == "glyphicon-edit") {
task.editable="glyphicon-floppy-save";
}
else{
task.editable="glyphicon-edit"
}
}
Note: I've passed the glyphicon class directly to the button since it won't change.
Approach 2
You could also approach it another way and keep the condition in the HTML
<button class="glyphicon" ng-class="task.editable ? 'glyphicon-edit': 'glyphicon-floppy-save'" ng-click="editTask(task)"></button>
And your controller could just update the editable property
$scope.editTask = function(task){
task.editable = !task.editable;
}
Set the editable property on the task itself and then use task.editable. This will be a unique property for each task
you need to make some changes to your code. I'm gonna provide you the code I used in order to achieve what I believe is your goal, and will then explain the reasoning behind it.
<table>
<tr ng-repeat="task in tasks">
<td>{{task.Name}}</td>
<td>{{task.Comments}}</td>
<td>{{task.Project}}</td>
<td>{{task.Duration}}</td>
<td>
<button class={{task.editable}} ng-click="editTask($index)"></button>
<button class="glyphicon glyphicon-trash"></button>
</td>
</tr>
</table>
As you can see, I included an attribute inside the task called editable. I'll be using this attribute to change the class. You'll also notice I', using $index. This is a default counter for ng-repeat.
$scope.tasks.push({Name: 'Jorge', Comments: 'Comentario',Project: 'Tengu', Duration: 45, editable: "glyphicon glyphicon-trash"});
$scope.tasks.push({Name: 'Mermelada', Comments: 'Comentario2',Project: 'DM-300', Duration: 30, editable: "glyphicon glyphicon-trash"});
You'll need to add the editable properties to your objects.
$scope.editTask = function(id){
if($scope.tasks[id].editable == "glyphicon glyphicon-trash"){
$scope.tasks[id].editable="glyphicon glyphicon-floppy-save";
} else{
$scope.tasks[id].editable="glyphicon glyphicon-trash"
}
}
I don't believe this needs much explanation. Please let me know otherwise.
If you simply want to switch between class just use ng-class
exemple, you have a variable leftOrRight, we will assume that you have two class in you css file: floatLeft and floatRight (with the attribute float: right/left; )
ng-class="{ floatRight : leftOrRight == 'right', floatLeft : leftOrRight == 'left' }"
If you set leftOrRight to "right" you will have the same thing as class="floatRight" for exemple.