Reputation: 1408
I'm wondering what the best way to approach this problem is and I'm very new to TypeScript and Angular. Using Angular 5.
Anyway. I have a list of elements on a page via a table.
This is the code that controls said list.
<tbody>
<tr class="text-center" *ngFor="let topic of topics">
<td *ngIf="!editTopicMode">{{ topic.name }}</td>
<td id="{{topic.id}}" *ngIf="editTopicMode">
<form>
<div class="form-group">
<input class="form-control" type="text" name="name" value="{{topic.name}}" />
</div>
</form>
</td>
<td>
<div *ngIf="!editTopicMode" class="btn-group btn-group-sm">
<button class="btn btn-link" (click)="editTopicBtnClick(topic.id)">
<i class="fa fa-pencil fa-2x" aria-hidden="true"></i>
</button>
<button class="btn btn-link">
<i class="fa fa-trash fa-2x" aria-hidden="true"></i>
</button>
</div>
<div *ngIf="editTopicMode" class="btn-group-sm">
<button class="ml-2 btn btn-sm btn-outline-secondary" (click)="cancelEditMode()">Cancel</button>
<button class="ml-2 btn btn-sm btn-outline-primary">Save</button>
</div>
</td>
</tr>
</tbody>
What I'm aiming to do is that if a user clicks on the pencil(edit) icon, then the adjacent div changes from just a regular td to an input and the edit/delete buttons to change to a cancelEdit/save edits button group. (I know that I need to change the html a bit because the buttons aren't in the form element currently, but I'm not there on the wiring it up part).
I've thought of two ways to do this. 1) with ngIf's so that I can conserve the elements that are rendered and the edit/cancel buttons toggle the editMode; or 2) use ngClass and toggle display:none css classes for the button clicked.
Right now, when you click the edit button, regardless of which edit button you click, it flips all the columns to inputs, rather than just the row the user wants to edit.
Here's my component ts:
import { Component, OnInit, TemplateRef, ElementRef, ViewChild, Inject } from '@angular/core';
import { Topic } from '../models/topic';
import { TopicService } from '../services/topicService/topics.service';
import { AlertifyService } from '../services/alertify/alertify.service';
import { ActivatedRoute } from '@angular/router';
import { DOCUMENT } from '@angular/common';
@Component({
selector: 'app-topics',
templateUrl: './topics.component.html',
styleUrls: ['./topics.component.css']
})
export class TopicComponent implements OnInit {
@ViewChild('topicId') topicId: ElementRef;
topics: Topic[];
newTopic: Topic = {
id: 0,
name: '',
};
editTopicMode = false;
constructor(
@Inject(DOCUMENT) document,
private topicsService: TopicService,
private alertify: AlertifyService,
private route: ActivatedRoute
) { }
ngOnInit() {
//this.route.data.subscribe(data => {
// this.topics = data['topics'];
//})
this.getTopics();
}
getTopics() {
this.topicsService.getAllTopics()
.subscribe(data => {
this.topics = data;
}, error => {
this.alertify.error(error);
});
}
addTopic() {
this.topicsService.createTopic(this.newTopic)
.subscribe((topic: Topic) => {
this.topics.push(topic);
this.alertify.success(this.newTopic.name + ' added as a new topic.');
this.newTopic.name = '';
},
(err: any) => {
this.alertify.error(err);
}
)
}
editTopicBtnClick(event) {
console.log(event);
this.editTopicMode = true;
console.log(document.getElementById(event));
}
cancelEditMode() {
this.editTopicMode = !this.editTopicMode;
}
}
Any thoughts on the best (most efficient) way to make this happen?
Upvotes: 2
Views: 6644
Reputation: 36624
You've done all the hard work already.
For single item editing, all that's left is: change editTopicMode
to something like editTopicId
.
Then you can:
topic.id
on edit enabled, and null
for example on edit closed*ngIf
to editTopicId === topic.id
(or !==
as needed)And that should be all.
If you want to enable multiple editing, just add a property called isInEditMode
to each topic.
*ngIf
check becomes topic.isInEditMode
isInEditMode
property at all is just like false
, because undefined
is a falsy valuetopic.isInEditMode
to true
on editing enabled, false
on editing closedUpvotes: 1
Reputation: 728
Using *ngIf is fine just make sure that you set the *ngIf variable to point to somethign specific to the particular row of the *ngFor
this example could be cleaner but you could accomplish it as simply as
<button (click)="topic.edit = true" *ngIf="topic.edit === false">edit</button>
<button (click)="topic.edit = false" *ngIf="topic.edit === true">cancel</button>
Upvotes: 0