Blog Post Update: The Ultimate Step-by-Step Guide


🚀

ā§§. āĻŦā§āϝāĻžāĻ•āĻāĻ¨ā§āĻĄ (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 UpdateSetValues()āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸā§‡āϰ āϏāĻŦ āϏāĻžāϧāĻžāϰāĻŖ āĻ•āϞāĻžāĻŽ āĻāĻ•āĻŦāĻžāϰ⧇ āφāĻĒāĻĄā§‡āϟ āĻ•āϰāϤ⧇āĨ¤
Many-to-ManyClear() + Add()āϰāĻŋāϞ⧇āĻļāύāĻļāĻŋāĻĒ āĻŸā§‡āĻŦāĻŋāϞāϕ⧇ āĻ•āύāĻĢā§āϞāĻŋāĻ•ā§āϟ āĻ›āĻžāĻĄāĻŧāĻž āφāĻĒāĻĄā§‡āϟ āĻ•āϰāϤ⧇āĨ¤
Eager Loading.Include()āϜāϝāĻŧ⧇āύ āϕ⧁āϝāĻŧ⧇āϰāĻŋ āϚāĻžāϞāĻŋāϝāĻŧ⧇ āϰāĻŋāϞ⧇āĻŸā§‡āĻĄ āĻĄāĻžāϟāĻž āφāύāϤ⧇āĨ¤
Reactive Dataeffect()āϏāĻŋāĻ—āĻ¨ā§āϝāĻžāϞ⧇ āĻĄāĻžāϟāĻž āφāϏāĻžāϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻĨ⧇ āĻĢāĻ°ā§āĻŽ āφāĻĒāĻĄā§‡āϟ āĻ•āϰāϤ⧇āĨ¤
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-āϰ āϏāĻŽā§āĻĒāĻ°ā§āĻ• āϝ⧇āĻ­āĻžāĻŦ⧇ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞ āĻ•āϰ⧇āĻ›āĻŋ:

  1. Frontend: āĻ•ā§āϝāĻžāϟāĻžāĻ—āϰāĻŋāϗ⧁āϞ⧋āϕ⧇ āφāϞāĻžāĻĻāĻž āĻāĻ•āϟāĻŋ string[] āĻ…ā§āϝāĻžāϰ⧇āϤ⧇ āϰ⧇āϖ⧇āĻ›āĻŋāĨ¤
  2. DTO: āϏāĻžāĻŦāĻŽāĻŋāϟ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āϏ⧇āχ categoryIds āϞāĻŋāĻ¸ā§āϟāϟāĻŋ āĻŦā§āϝāĻžāĻ•āĻāĻ¨ā§āĻĄā§‡ āĻĒāĻžāĻ āĻŋāϝāĻŧ⧇āĻ›āĻŋāĨ¤
  3. 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()), āϤāĻ–āύ āϝāĻž āϘāϟāϛ⧇:

  1. Iterate (āϘ⧁āϰ⧇ āĻĻ⧇āĻ–āĻž): āϏ⧇ āϞāĻŋāĻ¸ā§āĻŸā§‡āϰ āĻĒā§āϰāĻĨāĻŽ āĻ•ā§āϝāĻžāϟāĻžāĻ—āϰāĻŋ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟāϟāĻŋ āύāĻŋāϞ (āϝāĻžāϕ⧇ āφāĻŽāϰāĻž x āĻŦāϞāĻ›āĻŋ)āĨ¤
  2. Transform (āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ): āϏ⧇ āĻ“āχ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āĻĨ⧇āϕ⧇ āĻļ⧁āϧ⧁ id āĻĒā§āϰāĻĒāĻžāĻ°ā§āϟāĻŋāϟāĻŋ āĻŦ⧇āϰ āĻ•āϰāϞ āĻāĻŦāĻ‚ āϏ⧇āϟāĻŋāϕ⧇ .toString() āĻ•āϰ⧇ āĻāĻ•āϟāĻŋ āĻĒāĻŋāĻ“āϰ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚-āĻ āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ āĻ•āϰāϞāĨ¤
  3. Collect (āϜāĻŽāĻž āĻ•āϰāĻž): āĻāχ āύāϤ⧁āύ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āφāχāĻĄāĻŋāϟāĻŋāϕ⧇ āϏ⧇ āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āϞāĻŋāĻ¸ā§āĻŸā§‡ āϰāĻžāĻ–āϞāĨ¤
  4. Repeat (āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ): āϏ⧇ āĻĒāϰ⧇āϰ āĻ•ā§āϝāĻžāϟāĻžāĻ—āϰāĻŋāϰ āϜāĻ¨ā§āϝ āĻāĻ•āχ āĻ•āĻžāϜ āĻ•āϰāϞāĨ¤

āϰ⧇āϜāĻžāĻ˛ā§āϟ āϕ⧀ āĻšāĻšā§āϛ⧇?

āϏāĻŦāĻļ⧇āώ⧇ āφāĻĒāύāĻŋ āĻāχāϰāĻ•āĻŽ āĻāĻ•āϟāĻŋ āύāĻŋāϟ āĻāĻ¨ā§āĻĄ āĻ•ā§āϞāĻŋāύ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻ…ā§āϝāĻžāϰ⧇ āĻĒāĻžāĻšā§āϛ⧇āύ:

TypeScript

// selectedCategoryIds āĻāϰ āĻŽāĻžāύ āĻšāĻŦ⧇ āĻāĻ–āύ āĻāϰāĻ•āĻŽ:
["guid-123", "guid-456"]

āϕ⧇āύ āĻāϟāĻŋ āĻĻāϰāĻ•āĻžāϰ āĻ›āĻŋāϞ?

  • āĻ…āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ āĻĄāĻžāϟāĻž āĻŦāĻžāĻĻ āĻĻ⧇āĻ“āϝāĻŧāĻž: āφāĻĒāύāĻžāϰ selectedCategoryIds āĻāϰ āϜāĻ¨ā§āϝ āĻĒ⧁āϰ⧋ āĻ•ā§āϝāĻžāϟāĻžāĻ—āϰāĻŋ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ (āύāĻžāĻŽ, āχāωāφāϰāĻāϞ āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞ) āĻĻāϰāĻ•āĻžāϰ āύ⧇āχ, āĻļ⧁āϧ⧁ ID āϟ⧁āϕ⧁ āĻĻāϰāĻ•āĻžāϰāĨ¤
  • āϟāĻžāχāĻĒ āĻŽā§āϝāĻžāϚāĻŋāĻ‚: āĻĄāĻžāϟāĻžāĻŦ⧇āϏ āĻĨ⧇āϕ⧇ āφāχāĻĄāĻŋāϗ⧁āϞ⧋ āĻšāϝāĻŧāϤ⧋ Guid āĻĢāϰāĻŽā§āϝāĻžāĻŸā§‡ āφāϏāĻ›āĻŋāϞ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āφāĻĒāύāĻžāϰ āĻĢā§āϰāĻ¨ā§āϟāĻāĻ¨ā§āĻĄ āĻšā§‡āĻ•āĻŦāĻ•ā§āϏ⧇āϰ āϜāĻ¨ā§āϝ āϏ⧇āϗ⧁āϞ⧋āϕ⧇ āĻĒāĻŋāĻ“āϰ string āĻšāĻ“āϝāĻŧāĻž āϜāϰ⧁āϰāĻŋ āĻ›āĻŋāϞāĨ¤

āĻāĻ•āϟāĻŋ āĻŦāĻžāĻ¸ā§āϤāĻŦ āωāĻĻāĻžāĻšāϰāϪ⧇āϰ āϏāĻžāĻĨ⧇ āϤ⧁āϞāύāĻž:

āϚāĻŋāĻ¨ā§āϤāĻž āĻ•āϰ⧁āύ āφāĻĒāύāĻžāϰ āĻ•āĻžāϛ⧇ āĻāĻ• āĻā§āĻĄāĻŧāĻŋ āφāĻŽ āφāϛ⧇āĨ¤ āφāĻĒāύāĻŋ āϚāĻžāĻšā§āϛ⧇āύ āĻļ⧁āϧ⧁ āφāĻŽā§‡āϰ āφāρāϟāĻŋāϗ⧁āϞ⧋ āϏāĻ‚āĻ—ā§āϰāĻš āĻ•āϰāϤ⧇ āĻāĻŦāĻ‚ āφāρāϟāĻŋāϗ⧁āϞ⧋āϕ⧇ āϧ⧁āϝāĻŧ⧇ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻ•āϰ⧇ (toString) āĻāĻ•āϟāĻŋ āĻŦāĻ•ā§āϏ⧇ āϰāĻžāĻ–āϤ⧇āĨ¤

  • āĻĒ⧁āϰ⧋ āφāĻŽ = category āĻ…āĻŦāĻœā§‡āĻ•ā§āϟāĨ¤
  • āφāρāϟāĻŋ = idāĨ¤
  • āϧ⧁āϝāĻŧ⧇ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻ•āϰāĻž = .toString()āĨ¤
  • āύāϤ⧁āύ āĻŦāĻ•ā§āϏ = selectedCategoryIds āĻ…ā§āϝāĻžāϰ⧇āĨ¤
  • āĻāχ āĻĒ⧁āϰ⧋ āĻĒā§āϰāϏ⧇āϏāϟāĻŋ āϝ⧇ āĻŽā§‡āĻļāĻŋāύ āĻĻāĻŋāϝāĻŧ⧇ āĻ•āϰāϛ⧇āύ = .map()āĨ¤

āĻāĻ–āύ āĻ•āĻŋ .map() āĻāϰ āĻ•āĻžāϜāϟāĻž āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻšāϝāĻŧ⧇āϛ⧇? āĻāϟāĻŋ āĻŽā§‚āϞāϤ āĻĄāĻžāϟāĻžāϕ⧇ āφāĻĒāύāĻžāϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύāĻŽāϤ⧋ “āĻĢāĻŋāĻ˛ā§āϟāĻžāϰ” āĻŦāĻž “āϰāĻŋāĻĢāĻžāχāύ” āĻ•āϰ⧇ āύ⧇āϝāĻŧāĨ¤

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top