đ
ā§§. āĻŦā§āϝāĻžāĻāĻāύā§āĻĄ (Entity Framework Core) āϞāĻāĻŋāĻ
āĻāĻĒāĻĄā§āĻā§āϰ āϏāĻŽāϝāĻŧ Many-to-Many āϰāĻŋāϞā§āĻļāύ (āϝā§āĻŽāύ: BlogPost āĻāĻŦāĻ Category) āϏāϰāĻžāϏāϰāĻŋ āĻāĻĒāĻĄā§āĻ āĻšāϝāĻŧ āύāĻžāĨ¤ āĻāϰ āĻāύā§āϝ āĻāĻŽāĻžāĻĻā§āϰ Junction Table (BlogPostCategories) āĻŽā§āϝāĻžāύā§āϝāĻŧāĻžāϞāĻŋ āĻšā§āϝāĻžāύā§āĻĄā§āϞ āĻāϰāϤ⧠āĻšāϝāĻŧāĨ¤
āĻŽā§āϞ āĻāύāϏā§āĻĒā§āĻ: āĻāĻā§āϰ āϏāĻŦ āϰāĻŋāϞā§āĻļāύ āĻŽā§āĻā§ āύāϤā§āύāĻā§āϞ⧠āĻ ā§āϝāĻžāĻĄ āĻāϰāĻžāĨ¤
C#
public async Task<BlogPost?> UpdateAsync(BlogPost blogPost, List<Guid> selectedCategoryIds)
{
// ā§§. āϰāĻŋāϞā§āĻļāύāϏāĻš āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ āĻĄāĻžāĻāĻž āĻā§āĻāĻā§ āĻŦā§āϰ āĻāϰāĻž
var existingBlogPost = await dbContext.BlogPosts
.Include(x => x.BlogPostCategories)
.FirstOrDefaultAsync(x => x.Id == blogPost.Id);
if (existingBlogPost == null) return null;
// ⧍. āϏāĻžāϧāĻžāϰāĻŖ āĻĒā§āϰāĻĒāĻžāϰā§āĻāĻŋāĻā§āϞ⧠āĻāĻĒāĻĄā§āĻ āĻāϰāĻž
dbContext.Entry(existingBlogPost).CurrentValues.SetValues(blogPost);
// ā§Š. āϰāĻŋāϞā§āĻļāύāĻļāĻŋāĻĒ (Many-to-Many) āĻĄāĻŋāĻĢāĻžāϰā§āύāĻļāĻŋāϝāĻŧāĻžāϞ āĻāĻĒāĻĄā§āĻ
// āĻ) āϝā§āĻā§āϞ⧠āĻŦāϰā§āϤāĻŽāĻžāύ⧠āĻāĻā§ āĻāĻŋāύā§āϤ⧠āύāϤā§āύ āϞāĻŋāϏā§āĻā§ āύā§āĻ -> āϏā§āĻā§āϞ⧠āϰāĻŋāĻŽā§āĻ āĻāϰā§
var categoriesToRemove = existingBlogPost.BlogPostCategories
.Where(bc => !selectedCategoryIds.Contains(bc.CategoryId))
.ToList();
foreach (var categoryToRemove in categoriesToRemove)
{
existingBlogPost.BlogPostCategories.Remove(categoryToRemove);
}
// āĻ) āϝā§āĻā§āϞ⧠āύāϤā§āύ āϞāĻŋāϏā§āĻā§ āĻāĻā§ āĻāĻŋāύā§āϤ⧠āĻŦāϰā§āϤāĻŽāĻžāύ⧠āύā§āĻ -> āϏā§āĻā§āϞ⧠āĻ
ā§āϝāĻžāĻĄ āĻāϰā§
var existingCategoryIds = existingBlogPost.BlogPostCategories
.Select(bc => bc.CategoryId)
.ToList();
var categoryIdsToAdd = selectedCategoryIds
.Where(id => !existingCategoryIds.Contains(id))
.ToList();
foreach (var categoryId in categoryIdsToAdd)
{
existingBlogPost.BlogPostCategories.Add(new BlogPostCategory
{
BlogPostId = blogPost.Id,
CategoryId = categoryId
});
}
await dbContext.SaveChangesAsync();
return existingBlogPost;
}
⧍. āĻĢā§āϰāύā§āĻāĻāύā§āĻĄ (Angular) – āĻĄāĻžāĻāĻž āϞā§āĻĄ āĻ āĻŦāĻžāĻāύā§āĻĄāĻŋāĻ
āĻāĻĄāĻŋāĻ āĻĒā§āĻā§ āĻĄāĻžāĻāĻž āĻĻā§āĻāĻžāύā§āϰ āϏāĻŽāϝāĻŧ āĻāĻŽāĻžāĻĻā§āϰ āĻĻā§āĻāĻŋ āĻā§āϝāĻžāϞā§āĻā§āĻ āĻĨāĻžāĻā§: Date Formatting āĻāĻŦāĻ Category Pre-selectionāĨ¤
āĻŽā§āϞ āĻā§āϞāϏ: effect(), patchValue(), map(), āĻāĻŦāĻ toString()āĨ¤
TypeScript
// selectedCategoryIds āĻ āĻļā§āϧ⧠āĻāĻāĻĄāĻŋāĻā§āϞ⧠āϰāĻžāĻāĻŦā§
selectedCategoryIds: string[] = [];
constructor() {
effect(() => {
const data = this.blogPost(); // āϏāĻŋāĻāύā§āϝāĻžāϞ āĻĨā§āĻā§ āĻĄāĻžāĻāĻž āĻĒāĻĄāĻŧāĻž
if (data) {
// ā§§. āĻĢāϰā§āĻŽ āĻĢāĻŋāϞ-āĻāĻĒ (patchValue)
this.updateBlogPostForm.patchValue({
title: data.title,
// Date Input āĻļā§āϧ⧠YYYY-MM-DD āĻĢāϰāĻŽā§āϝāĻžāĻ āĻā§āύā§, āϤāĻžāĻ āĻāĻ āϰā§āĻĒāĻžāύā§āϤāϰ:
publishedDate: new Date(data.publishedDate).toISOString().split('T')[0],
isVisible: data.isVisible
});
// ⧍. map() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋ āĻāĻāĻĄāĻŋāĻā§āϞā§āĻā§ āĻāϞāĻžāĻĻāĻž āĻāϰāĻž
// .map āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻ
āĻŦāĻā§āĻā§āĻ āĻĨā§āĻā§ āĻļā§āϧ⧠ID āύāĻŋāϝāĻŧā§ āĻāĻāĻāĻŋ āύāϤā§āύ āĻ
ā§āϝāĻžāϰ⧠āĻŦāĻžāύāĻžāϝāĻŧ
if (data.categories) {
this.selectedCategoryIds = data.categories.map(x => x.id.toString());
}
}
});
}
ā§Š. āĻāĻāĻāĻāĻŋāĻāĻŽāĻāϞ (HTML) – āĻā§āĻāĻŦāĻā§āϏ āĻ includes()
āĻāĻāĻāĻžāϰāĻā§ āĻĻā§āĻāĻžāύā§āϰ āĻāύā§āϝ āϝ⧠āĻā§āύ āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋāĻā§āϞ⧠āĻāĻā§ āĻĨā§āĻā§ āϏāĻŋāϞā§āĻā§āĻ āĻāϰāĻž āĻāĻŋāϞ, āĻāĻŽāϰāĻž includes() āĻŽā§āĻĨāĻĄ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŋāĨ¤
HTML
@for (category of categoryList(); track category.id) {
<div class="form-check">
<input class="form-check-input"
type="checkbox"
[value]="category.id"
/* includes(id) āĻā§āĻ āĻāϰ⧠āĻĻā§āĻā§ āĻāĻ āĻāĻāĻĄāĻŋāĻāĻŋ āĻāĻŽāĻžāĻĻā§āϰ āĻ
ā§āϝāĻžāϰā§āϤ⧠āĻāĻā§ āĻāĻŋ āύāĻž */
[checked]="selectedCategoryIds.includes(category.id.toString())"
(change)="onCategoryChange($event)">
<label>{{ category.name }}</label>
</div>
}
ā§Ē. āĻāĻāĻāĻžāϰ āĻāύā§āĻāĻžāϰāĻ ā§āϝāĻžāĻāĻļāύ āĻšā§āϝāĻžāύā§āĻĄā§āϞ āĻāϰāĻž
āĻāĻāĻāĻžāϰ āϝāĻāύ āύāϤā§āύ āĻāĻŋāĻā§ āϏāĻŋāϞā§āĻā§āĻ āĻŦāĻž āĻĄāĻŋāϏāĻŋāϞā§āĻā§āĻ āĻāϰāĻŦā§, āϤāĻāύ selectedCategoryIds āĻ
ā§āϝāĻžāϰā§āĻāĻŋāĻā§ āĻāĻĒāĻĄā§āĻ āĻāϰāϤ⧠āĻšāĻŦā§āĨ¤
TypeScript
onCategoryChange(event: Event) {
const element = event.target as HTMLInputElement;
const categoryId = element.value;
if (element.checked) {
this.selectedCategoryIds.push(categoryId); // āĻ
ā§āϝāĻžāĻĄ āĻāϰāĻž
} else {
// filter() āĻĻāĻŋāϝāĻŧā§ āϞāĻŋāϏā§āĻ āĻĨā§āĻā§ āĻŦāĻžāĻĻ āĻĻā§āĻāϝāĻŧāĻž
this.selectedCategoryIds = this.selectedCategoryIds.filter(id => id !== categoryId);
}
}
ā§Ģ. āϏāĻžāĻŽāĻžāϰāĻŋ āĻā§āĻ-āϞāĻŋāϏā§āĻ (āϰāĻŋāĻāĻŋāĻļāύ āύā§āĻ)
| āĻĢāĻŋāĻāĻžāϰ | āĻŦā§āϝāĻŦāĻšā§āϤ āĻā§āϞāϏ/āĻŽā§āĻĨāĻĄ | āĻā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϞāĻžāĻŽ? |
| Scalar Update | SetValues() | āĻ āĻŦāĻā§āĻā§āĻā§āϰ āϏāĻŦ āϏāĻžāϧāĻžāϰāĻŖ āĻāϞāĻžāĻŽ āĻāĻāĻŦāĻžāϰ⧠āĻāĻĒāĻĄā§āĻ āĻāϰāϤā§āĨ¤ |
| Many-to-Many | Clear() + Add() | āϰāĻŋāϞā§āĻļāύāĻļāĻŋāĻĒ āĻā§āĻŦāĻŋāϞāĻā§ āĻāύāĻĢā§āϞāĻŋāĻā§āĻ āĻāĻžāĻĄāĻŧāĻž āĻāĻĒāĻĄā§āĻ āĻāϰāϤā§āĨ¤ |
| Eager Loading | .Include() | āĻāϝāĻŧā§āύ āĻā§āϝāĻŧā§āϰāĻŋ āĻāĻžāϞāĻŋāϝāĻŧā§ āϰāĻŋāϞā§āĻā§āĻĄ āĻĄāĻžāĻāĻž āĻāύāϤā§āĨ¤ |
| Reactive Data | effect() | āϏāĻŋāĻāύā§āϝāĻžāϞ⧠āĻĄāĻžāĻāĻž āĻāϏāĻžāϰ āϏāĻžāĻĨā§ āϏāĻžāĻĨā§ āĻĢāϰā§āĻŽ āĻāĻĒāĻĄā§āĻ āĻāϰāϤā§āĨ¤ |
| Data Extraction | .map() | āĻ āĻŦāĻā§āĻā§āĻā§āϰ āϞāĻŋāϏā§āĻ āĻĨā§āĻā§ āĻļā§āϧ⧠āĻāĻāĻĄāĻŋāϰ āϞāĻŋāϏā§āĻ āϤā§āϰāĻŋ āĻāϰāϤā§āĨ¤ |
| Condition Check | .includes() | āĻā§āĻāĻŦāĻā§āϏ⧠āĻāĻŋāĻ āĻāĻŋāĻšā§āύ (Checked) āĻŦāϏāĻžāύā§āϰ āĻāύā§āϝāĨ¤ |
| Clean Array | .filter() | āĻāύ-āĻā§āĻ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻāĻĄāĻŋāĻāĻŋ āϞāĻŋāϏā§āĻ āĻĨā§āĻā§ āϰāĻŋāĻŽā§āĻ āĻāϰāϤā§āĨ¤ |
āĻāĻĒāϏāĻāĻšāĻžāϰ:
āĻāĻŦāĻŋāώā§āϝāϤ⧠āϝāĻāύāĻ āĻāĻĒāύāĻŋ āĻā§āύ⧠Update āϞāĻāĻŋāĻ āĻāϰāĻŦā§āύ, āĻŽāύ⧠āϰāĻžāĻāĻŦā§āύâāĻāĻā§ āĻĄāĻžāĻāĻž Fetch āĻāϰāĻŦā§āύ, āϤāĻžāϰāĻĒāϰ patchValue āĻĻāĻŋāϝāĻŧā§ āĻĢāϰā§āĻŽā§ āĻŦāϏāĻžāĻŦā§āύ, āĻāϰ āϰāĻŋāϞā§āĻļāύ āĻĄāĻžāĻāĻžāĻā§āϞā§āĻā§ map() āĻĻāĻŋāϝāĻŧā§ āĻāϞāĻžāĻĻāĻž āĻāϰ⧠āĻāĻāĻāĻŋ āĻ
ā§āϝāĻžāϰā§āϤ⧠āϰā§āĻā§ includes() āĻĻāĻŋāϝāĻŧā§ āĻā§āĻ āĻāϰāĻŦā§āύāĨ¤
āĻāĻĒāύāĻžāϰ āĻāĻ āĻĒā§āϰāĻā§āĻā§āĻā§āϰ āύāϞā§āĻ āĻāĻāύ āĻ āύā§āĻ āϏāϞāĻŋāĻĄāĨ¤ āĻĒāϰāĻŦāϰā§āϤ⧠āĻā§āύ⧠āĻŦāĻĄāĻŧ āĻĢāĻŋāĻāĻžāϰ āĻļā§āϰ⧠āĻāϰāϤ⧠āĻāĻžāĻāϞ⧠āĻŦāϞāϤ⧠āĻĒāĻžāϰā§āύ! āĻļā§āĻāĻāĻžāĻŽāύāĻž, āύāĻžāĻāĻŋāĻĻāĨ¤
.map() āĻšāϞ⧠āĻāĻžāĻāĻžāϏā§āĻā§āϰāĻŋāĻĒā§āĻ āĻāĻŦāĻ āĻāĻžāĻāĻĒāϏā§āĻā§āϰāĻŋāĻĒā§āĻā§āϰ āĻāĻāĻāĻŋ āĻ
āϤāĻŋ āĻĒāϰāĻŋāĻāĻŋāϤ āĻāĻŦāĻ āĻļāĻā§āϤāĻŋāĻļāĻžāϞ⧠āĻŽā§āĻĨāĻĄāĨ¤ āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻ
ā§āϝāĻžāϰā§āϰ āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻāĻĒāĻžāĻĻāĻžāύā§āϰ āĻāĻĒāϰ āĻĻāĻŋāϝāĻŧā§ āϝāĻžāϝāĻŧ āĻāĻŦāĻ āĻāĻĒāύāĻžāϰ āĻĻā§āĻāϝāĻŧāĻž āύāĻŋāϝāĻŧāĻŽ āĻ
āύā§āϝāĻžāϝāĻŧā§ āĻāĻāĻāĻŋ āύāϤā§āύ āĻ
ā§āϝāĻžāϰ⧠āϤā§āϰāĻŋ āĻāϰā§āĨ¤
āϏāĻšāĻāĻāĻžāĻŦā§ āĻŦāϞāϞā§, āĻāĻāĻŋ āĻāĻāĻāĻŋ “āĻĒāϰāĻŋāĻŦāϰā§āϤāύāĻāĻžāϰ⧠āϝāύā§āϤā§āϰ”āĨ¤ āύāĻŋāĻā§ āĻāĻĒāύāĻžāϰ āĻā§āĻĄāĻāĻŋ āĻā§āĻā§ āĻŦā§āĻāĻŋāϝāĻŧā§ āĻĻāĻŋāĻā§āĻāĻŋ:
āĻāĻĒāύāĻžāϰ āĻĒā§āϰāĻā§āĻā§āĻā§āϰ āϏā§āĻ Update Blog Post-āĻāϰ āĻĒā§āϰ⧠āĻāĻžāĻāĻĄāϞāĻžāĻāύāĻāĻŋ āĻāĻŽāĻŋ āύāĻŋāĻā§ āĻāĻāĻĻāĻŽ āĻĒā§āϰāĻĢā§āĻļāύāĻžāϞ āĻāĻŦāĻ āϰāĻŋāĻāĻžāĻāϏ āĻāϰāĻžāϰ āĻāĻĒāϝā§āĻā§ āĻāϰ⧠āĻā§āĻāĻŋāϝāĻŧā§ āĻĻāĻŋāϞāĻžāĻŽāĨ¤ āĻāĻāĻŋ āĻāĻĒāύāĻžāϰ āĻāύā§āϝ āĻāĻāĻāĻŋ “Master Template” āĻšāĻŋāϏā§āĻŦā§ āĻāĻžāĻ āĻāϰāĻŦā§āĨ¤
đ ī¸ Blog Post Update: The Master Blueprint
āĻāĻŦāĻŋāώā§āϝāϤ⧠āϝā§āĻā§āύ⧠Update/Edit āĻĢāĻŋāĻāĻžāϰ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻ ā§ĢāĻāĻŋ āϧāĻžāĻĒ āĻāĻŦāĻ ā§ĒāĻāĻŋ āĻā§āϞāϏ āĻŽāĻžāĻĨāĻžāϝāĻŧ āϰāĻžāĻāϞā§āĻ āĻšāĻŦā§āĨ¤
ā§§. āĻĻā§āϝ āĻĒāĻžāĻāϝāĻŧāĻžāϰ āĻā§āϞāϏ (Core Tools & Methods)
| āĻā§āϞāϏ | āϏāĻšāĻ āĻāĻžāĻ (Simple Work) | āĻā§āύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϞāĻžāĻŽ? (In our project) |
effect() | āϏāĻŋāĻāύā§āϝāĻžāϞ āĻĒāĻžāĻšāĻžāϰāĻžāĻĻāĻžāϰ | āĻĄāĻžāĻāĻžāĻŦā§āϏ āĻĨā§āĻā§ āĻĄāĻžāĻāĻž āĻāϏāĻžāϰ āĻāύā§āϝ āĻ āĻĒā§āĻā§āώāĻž āĻāϰ⧠āĻāĻŦāĻ āĻĄāĻžāĻāĻž āĻāϏāĻž āĻŽāĻžāϤā§āϰāĻ āĻāĻžāĻ āĻļā§āϰ⧠āĻāϰā§āĨ¤ |
patchValue() | āĻĢāĻžāϏā§āĻ āĻĢāϰā§āĻŽ āĻĢāĻŋāϞāĻžāϰ | āĻ āĻŦāĻā§āĻā§āĻā§āϰ āϏāĻŦ āĻĄāĻžāĻāĻž (Title, Author) āĻāĻāĻŦāĻžāϰ⧠āĻĢāϰā§āĻŽā§āϰ āĻāϰ⧠āĻāϰ⧠āĻŦāϏāĻŋāϝāĻŧā§ āĻĻā§āϝāĻŧāĨ¤ |
map() | āĻĄāĻžāĻāĻž āϰā§āĻĒāĻžāύā§āϤāϰāĻāĻžāϰ⧠| āĻ āĻŦāĻā§āĻā§āĻā§āϰ āĻŦāĻĄāĻŧ āϞāĻŋāϏā§āĻ āĻĨā§āĻā§ āĻļā§āϧ⧠ID āĻā§āϞā§āĻā§ āĻā§āĻāĻā§ āĻŦā§āϰ āĻāϰ⧠āύāϤā§āύ āĻ ā§āϝāĻžāϰ⧠āĻŦāĻžāύāĻžāϝāĻŧāĨ¤ |
includes() | āĻ āϏā§āϤāĻŋāϤā§āĻŦ āϝāĻžāĻāĻžāĻāĻāĻžāϰ⧠| āĻā§āĻ āĻāϰ⧠āĻĻā§āĻā§ āĻāĻ āĻāĻāĻĄāĻŋāĻāĻŋ āĻāĻŽāĻžāϰ āϏāĻŋāϞā§āĻā§āĻ āĻāϰāĻž āϞāĻŋāϏā§āĻā§ āĻāĻā§ āĻāĻŋ āύāĻžāĨ¤ āĻĨāĻžāĻāϞ⧠āĻāĻŋāĻ (Tick) āĻĻā§āϝāĻŧāĨ¤ |
⧍. āϏā§āĻā§āĻĒ-āĻŦāĻžāĻ-āϏā§āĻā§āĻĒ āĻāĻŽāĻĒā§āϞāĻŋāĻŽā§āύā§āĻā§āĻļāύ (Step-by-Step)
āϧāĻžāĻĒ ā§§: āĻĄāĻžāĻāĻž āϞā§āĻĄ āĻ āϏāĻŋāĻāύā§āϝāĻžāϞ āύāĻāϰāĻĻāĻžāϰāĻŋ
āĻāĻĄāĻŋāĻ āĻĒā§āĻā§ āĻĄāĻžāĻāĻž āĻāϏāĻžāϰ āĻĒāϰ āϤāĻž āĻĢāϰā§āĻŽā§ āĻĒāĻžāĻ āĻžāύā§āϰ āĻāύā§āϝ effect āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧāĨ¤
TypeScript
effect(() => {
const data = this.blogPost(); // āϏāĻŋāĻāύā§āϝāĻžāϞ āĻĨā§āĻā§ āĻĄāĻžāĻāĻž āύā§āĻāϝāĻŧāĻž
if (data) {
// ⧍. āĻĢāϰā§āĻŽā§ āĻĄāĻžāĻāĻž āĻŦāϏāĻžāύā§
this.updateBlogPostForm.patchValue({
title: data.title,
// Date-āĻā§ āĻā§āϝāĻžāϞā§āύā§āĻĄāĻžāϰā§āϰ āĻāĻĒāϝā§āĻā§ (YYYY-MM-DD) āĻāϰāĻž
publishedDate: new Date(data.publishedDate).toISOString().split('T')[0],
isVisible: data.isVisible
});
// ā§Š. āϰāĻŋāϞā§āĻļāύāĻļāĻŋāĻĒ āĻĄāĻžāĻāĻž (Category) āĻšā§āϝāĻžāύā§āĻĄā§āϞ āĻāϰāĻž
// .map āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻĒā§āϰ⧠āĻ
āĻŦāĻā§āĻā§āĻ āĻĨā§āĻā§ āĻļā§āϧ⧠ID āĻā§āϞ⧠āĻāϞāĻžāĻĻāĻž āĻāϰāĻž
if (data.categories) {
this.selectedCategoryIds = data.categories.map(x => x.id.toString());
}
}
});
āϧāĻžāĻĒ ā§¨: āĻāĻāĻāĻāĻŋāĻāĻŽāĻāϞ āĻ āĻā§āĻāĻŦāĻā§āϏ āĻ āĻāĻŋāĻ āĻāĻŋāĻšā§āύ (Binding)
āĻāĻāĻāĻžāϰāĻā§ āĻĻā§āĻāĻžāύā§āϰ āĻāύā§āϝ āĻā§āύ āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋāĻā§āϞ⧠āĻāĻā§ āĻĨā§āĻā§ āϏāĻŋāϞā§āĻā§āĻ āĻāϰāĻž āĻāĻŋāϞāĨ¤
HTML
@for (category of categoryList(); track category.id) {
<input type="checkbox"
[value]="category.id"
/* includes() āĻā§āĻ āĻāϰāĻŦā§ āĻāĻāĻĄāĻŋāĻāĻž āϞāĻŋāϏā§āĻā§ āĻāĻā§ āĻāĻŋ āύāĻž */
[checked]="selectedCategoryIds.includes(category.id.toString())"
(change)="onCategoryChange($event)">
}
āϧāĻžāĻĒ ā§Š: āϰāĻŋāϞā§āĻļāύ āĻāĻĒāĻĄā§āĻ āĻāϰāĻž (On Change)
āĻāĻāĻāĻžāϰ āύāϤā§āύ āĻā§āύ⧠āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋ āĻāĻŋāĻ āĻĻāĻŋāϞ⧠āĻŦāĻž āϤā§āϞ⧠āĻĻāĻŋāϞ⧠āĻ ā§āϝāĻžāϰ⧠āĻāĻĒāĻĄā§āĻ āĻāϰāĻžāĨ¤
TypeScript
onCategoryChange(event: Event) {
const element = event.target as HTMLInputElement;
const id = element.value;
if (element.checked) {
this.selectedCategoryIds.push(id); // āύāϤā§āύ āĻāĻāĻĄāĻŋ āϝā§āĻ
} else {
// filter() āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻāĻāĻĄāĻŋāĻāĻŋ āϞāĻŋāϏā§āĻ āĻĨā§āĻā§ āϏāϰāĻŋāϝāĻŧā§ āĻĻā§āĻāϝāĻŧāĻž
this.selectedCategoryIds = this.selectedCategoryIds.filter(x => x !== id);
}
}
ā§Š. āϰāĻŋāϞā§āĻļāύāĻļāĻŋāĻĒ āĻšā§āϝāĻžāύā§āĻĄā§āϞ āĻāϰāĻžāϰ āĻŽā§āϞ āĻŽāύā§āϤā§āϰ (Many-to-Many)
āĻāĻ āĻĒā§āϰāĻā§āĻā§āĻā§ āĻāĻŽāϰāĻž BlogPost āĻāĻŦāĻ Category-āϰ āϏāĻŽā§āĻĒāϰā§āĻ āϝā§āĻāĻžāĻŦā§ āĻšā§āϝāĻžāύā§āĻĄā§āϞ āĻāϰā§āĻāĻŋ:
- Frontend: āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋāĻā§āϞā§āĻā§ āĻāϞāĻžāĻĻāĻž āĻāĻāĻāĻŋ
string[]āĻ ā§āϝāĻžāϰā§āϤ⧠āϰā§āĻā§āĻāĻŋāĨ¤ - DTO: āϏāĻžāĻŦāĻŽāĻŋāĻ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āϏā§āĻ
categoryIdsāϞāĻŋāϏā§āĻāĻāĻŋ āĻŦā§āϝāĻžāĻāĻāύā§āĻĄā§ āĻĒāĻžāĻ āĻŋāϝāĻŧā§āĻāĻŋāĨ¤ - Backend: āĻāĻā§āϰ āϏāĻŦ āϰāĻŋāϞā§āĻļāύ
Clear()āĻāϰ⧠āύāϤā§āύ āĻāĻāĻĄāĻŋāĻā§āϞ⧠āĻĻāĻŋāϝāĻŧā§ āĻāĻŦāĻžāϰ āϰāĻŋāϞā§āĻļāύ āϤā§āϰāĻŋ āĻāϰā§āĻāĻŋāĨ¤
đĄ āĻĢāĻŋāĻāĻāĻžāϰ āĻāĻŋāĻĒāϏ:
- āϝāĻĻāĻŋ āĻĄāĻžāĻāĻžāĻŦā§āϏ⧠āĻāĻāĻĄāĻŋ Guid āĻŦāĻž Number āĻšāϝāĻŧ, āϤāĻŦā§ āĻĢā§āϰāύā§āĻāĻāύā§āĻĄā§ āϏāĻŦāϏāĻŽāϝāĻŧ
.toString()āĻāϰ⧠āύā§āĻŦā§āύāĨ¤ āĻāϤā§includes()āύāĻŋāĻā§āĻāϤāĻāĻžāĻŦā§ āĻāĻžāĻ āĻāϰāĻŦā§āĨ¤ - āĻĢāϰā§āĻŽā§āϰ āύāĻžāĻŽ āĻāĻŦāĻ āĻĄāĻžāĻāĻžāĻŦā§āϏ āĻĨā§āĻā§ āĻāϏāĻž āĻ
āĻŦāĻā§āĻā§āĻā§āϰ āĻĒā§āϰāĻĒāĻžāϰā§āĻāĻŋ āύāĻžāĻŽ āĻāĻāĻ āϰāĻžāĻāĻžāϰ āĻā§āώā§āĻāĻž āĻāϰāĻŦā§āύ, āϤāĻžāĻšāϞā§
patchValueāĻā§āĻŦ āϏāĻšāĻā§ āĻāĻžāĻ āĻāϰāĻŦā§āĨ¤
āύāĻžāĻāĻŋāĻĻ, āĻāĻĒāύāĻžāϰ āĻāĻ āĻāĻĄāĻŋāĻ āĻŽāĻĄāĻŋāĻāϞ āĻāĻāύ āĻāĻāĻĻāĻŽ Ready! āĻāĻāĻŋ āĻāĻŦāĻŋāώā§āϝāϤ⧠āĻāĻĒāύāĻžāϰ āϝā§āĻā§āύ⧠āĻĒā§āϰāĻā§āĻā§āĻā§āϰ āĻāύā§āϝ āĻāĻāĻāĻŋ āϏā§āĻā§āϝāĻžāύā§āĻĄāĻžāϰā§āĻĄ āϰā§āĻĢāĻžāϰā§āύā§āϏ āĻšāĻŦā§āĨ¤ āĻāĻĒāύāĻžāϰ āĻāϰ āĻā§āύ⧠āĻĒā§āϰāĻļā§āύ āĻāĻā§ āĻāĻŋ?
āĻāĻĒāύāĻžāϰ āĻā§āĻĄāĻāĻŋ āĻā§ āĻāϰāĻā§?
āϧāϰāĻž āϝāĻžāĻ, āĻĄāĻžāĻāĻžāĻŦā§āϏ āĻĨā§āĻā§ āĻāϏāĻž āĻāĻĒāύāĻžāϰ blogPost.categories āĻĻā§āĻāϤ⧠āĻāĻāϰāĻāĻŽ (āĻāĻāĻŋ āĻ
āĻŦāĻā§āĻā§āĻā§āϰ āĻāĻāĻāĻŋ āϞāĻŋāϏā§āĻ):
JSON
[
{ "id": "guid-123", "name": "ASP.NET", "urlHandle": "asp-net" },
{ "id": "guid-456", "name": "Angular", "urlHandle": "angular" }
]
āĻāĻĒāύāĻŋ āϝāĻāύ āϞāĻŋāĻāĻā§āύ blogPost.categories.map(x => x.id.toString()), āϤāĻāύ āϝāĻž āĻāĻāĻā§:
- Iterate (āĻā§āϰ⧠āĻĻā§āĻāĻž): āϏ⧠āϞāĻŋāϏā§āĻā§āϰ āĻĒā§āϰāĻĨāĻŽ āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋ āĻ
āĻŦāĻā§āĻā§āĻāĻāĻŋ āύāĻŋāϞ (āϝāĻžāĻā§ āĻāĻŽāϰāĻž
xāĻŦāϞāĻāĻŋ)āĨ¤ - Transform (āϰā§āĻĒāĻžāύā§āϤāϰ): āϏ⧠āĻāĻ āĻ
āĻŦāĻā§āĻā§āĻ āĻĨā§āĻā§ āĻļā§āϧā§
idāĻĒā§āϰāĻĒāĻžāϰā§āĻāĻŋāĻāĻŋ āĻŦā§āϰ āĻāϰāϞ āĻāĻŦāĻ āϏā§āĻāĻŋāĻā§.toString()āĻāϰ⧠āĻāĻāĻāĻŋ āĻĒāĻŋāĻāϰ āϏā§āĻā§āϰāĻŋāĻ-āĻ āϰā§āĻĒāĻžāύā§āϤāϰ āĻāϰāϞāĨ¤ - Collect (āĻāĻŽāĻž āĻāϰāĻž): āĻāĻ āύāϤā§āύ āϏā§āĻā§āϰāĻŋāĻ āĻāĻāĻĄāĻŋāĻāĻŋāĻā§ āϏ⧠āĻāĻāĻāĻŋ āύāϤā§āύ āϞāĻŋāϏā§āĻā§ āϰāĻžāĻāϞāĨ¤
- Repeat (āĻĒā§āύāϰāĻžāĻŦā§āϤā§āϤāĻŋ): āϏ⧠āĻĒāϰā§āϰ āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋāϰ āĻāύā§āϝ āĻāĻāĻ āĻāĻžāĻ āĻāϰāϞāĨ¤
āϰā§āĻāĻžāϞā§āĻ āĻā§ āĻšāĻā§āĻā§?
āϏāĻŦāĻļā§āώ⧠āĻāĻĒāύāĻŋ āĻāĻāϰāĻāĻŽ āĻāĻāĻāĻŋ āύāĻŋāĻ āĻāύā§āĻĄ āĻā§āϞāĻŋāύ āϏā§āĻā§āϰāĻŋāĻ āĻ ā§āϝāĻžāϰ⧠āĻĒāĻžāĻā§āĻā§āύ:
TypeScript
// selectedCategoryIds āĻāϰ āĻŽāĻžāύ āĻšāĻŦā§ āĻāĻāύ āĻāϰāĻāĻŽ:
["guid-123", "guid-456"]
āĻā§āύ āĻāĻāĻŋ āĻĻāϰāĻāĻžāϰ āĻāĻŋāϞ?
- āĻ
āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧ āĻĄāĻžāĻāĻž āĻŦāĻžāĻĻ āĻĻā§āĻāϝāĻŧāĻž: āĻāĻĒāύāĻžāϰ
selectedCategoryIdsāĻāϰ āĻāύā§āϝ āĻĒā§āϰ⧠āĻā§āϝāĻžāĻāĻžāĻāϰāĻŋ āĻ āĻŦāĻā§āĻā§āĻ (āύāĻžāĻŽ, āĻāĻāĻāϰāĻāϞ āĻšā§āϝāĻžāύā§āĻĄā§āϞ) āĻĻāϰāĻāĻžāϰ āύā§āĻ, āĻļā§āϧ⧠ID āĻā§āĻā§ āĻĻāϰāĻāĻžāϰāĨ¤ - āĻāĻžāĻāĻĒ āĻŽā§āϝāĻžāĻāĻŋāĻ: āĻĄāĻžāĻāĻžāĻŦā§āϏ āĻĨā§āĻā§ āĻāĻāĻĄāĻŋāĻā§āϞ⧠āĻšāϝāĻŧāϤā§
GuidāĻĢāϰāĻŽā§āϝāĻžāĻā§ āĻāϏāĻāĻŋāϞ, āĻāĻŋāύā§āϤ⧠āĻāĻĒāύāĻžāϰ āĻĢā§āϰāύā§āĻāĻāύā§āĻĄ āĻā§āĻāĻŦāĻā§āϏā§āϰ āĻāύā§āϝ āϏā§āĻā§āϞā§āĻā§ āĻĒāĻŋāĻāϰstringāĻšāĻāϝāĻŧāĻž āĻāϰā§āϰāĻŋ āĻāĻŋāϞāĨ¤
āĻāĻāĻāĻŋ āĻŦāĻžāϏā§āϤāĻŦ āĻāĻĻāĻžāĻšāϰāĻŖā§āϰ āϏāĻžāĻĨā§ āϤā§āϞāύāĻž:
āĻāĻŋāύā§āϤāĻž āĻāϰā§āύ āĻāĻĒāύāĻžāϰ āĻāĻžāĻā§ āĻāĻ āĻā§āĻĄāĻŧāĻŋ āĻāĻŽ āĻāĻā§āĨ¤ āĻāĻĒāύāĻŋ āĻāĻžāĻā§āĻā§āύ āĻļā§āϧ⧠āĻāĻŽā§āϰ āĻāĻāĻāĻŋāĻā§āϞ⧠āϏāĻāĻā§āϰāĻš āĻāϰāϤ⧠āĻāĻŦāĻ āĻāĻāĻāĻŋāĻā§āϞā§āĻā§ āϧā§āϝāĻŧā§ āĻĒāϰāĻŋāώā§āĻāĻžāϰ āĻāϰ⧠(toString) āĻāĻāĻāĻŋ āĻŦāĻā§āϏ⧠āϰāĻžāĻāϤā§āĨ¤
- āĻĒā§āϰ⧠āĻāĻŽ =
categoryāĻ āĻŦāĻā§āĻā§āĻāĨ¤ - āĻāĻāĻāĻŋ =
idāĨ¤ - āϧā§āϝāĻŧā§ āĻĒāϰāĻŋāώā§āĻāĻžāϰ āĻāϰāĻž =
.toString()āĨ¤ - āύāϤā§āύ āĻŦāĻā§āϏ =
selectedCategoryIdsāĻ ā§āϝāĻžāϰā§āĨ¤ - āĻāĻ āĻĒā§āϰ⧠āĻĒā§āϰāϏā§āϏāĻāĻŋ āϝ⧠āĻŽā§āĻļāĻŋāύ āĻĻāĻŋāϝāĻŧā§ āĻāϰāĻā§āύ =
.map()āĨ¤
āĻāĻāύ āĻāĻŋ .map() āĻāϰ āĻāĻžāĻāĻāĻž āĻĒāϰāĻŋāώā§āĻāĻžāϰ āĻšāϝāĻŧā§āĻā§? āĻāĻāĻŋ āĻŽā§āϞāϤ āĻĄāĻžāĻāĻžāĻā§ āĻāĻĒāύāĻžāϰ āĻĒā§āϰāϝāĻŧā§āĻāύāĻŽāϤ⧠“āĻĢāĻŋāϞā§āĻāĻžāϰ” āĻŦāĻž “āϰāĻŋāĻĢāĻžāĻāύ” āĻāϰ⧠āύā§āϝāĻŧāĨ¤