DEV Community

Connie Leung
Connie Leung

Posted on

Day 13 - Create a CoffeePlan Component with Prop

Table of Contents

Create a CoffeePlan Component

On day 13, I started refactoring the HTML code into a reusable CoffeePlan component. The component will accept a name input and display the input value in the HTML template.

Starter HTML Code

<div class="content">
  <h1 class="title">Coffee Plans</h1>

  <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>

  <div class="plans">
    <div class="plan">
      <div class="description">
        <span class="title"> The Single </span>
      </div>
    </div>

    <div class="plan">
      <div class="description">
        <span class="title"> The Curious </span>
      </div>
    </div>

    <div class="plan">
      <div class="description">
        <span class="title"> The Addict </span>
      </div>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

The following HTML block repeats four times except they have a title title. Therefore, it can extract into a Coffee

<div class="plan">
  <div class="description">
    <span class="title"> The Single </span>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Create the CoffeePlan Component without Props

Vue 3 application

  • Create a new components/CoffeePlan.vue file and update the template
<script setup lang="ts"></script>

<template>
    <div class="plan">
      <div class="description">
        <span class="title"> The Single </span>
      </div>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode
  • Import CoffeePlan to App.vue
<script setup lang="ts">
import CoffeePlan from './components/CoffeePlan.vue'
</script>

<template>
   <div class="content">
      <h1 class="title">Coffee Plans</h1>

      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>

      <div class="plans">
        <CoffeePlan />
        <CoffeePlan />
        <CoffeePlan />
        <CoffeePlan />       
      </div>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode
  • At this moment, we will see four CoffeePlan components with the title 'The Single'. Later, we will refactor this component to accept different titles.

SvelteKit application

  • Create a new lib/coffee-plan.svelte file and update the template
<script lang="ts"></script>

<div class="plan">
  <div class="description">
    <span class="title"> The Single </span>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode
  • export the new component from lib/index.ts
export * from './coffee-plan.svelte';
Enter fullscreen mode Exit fullscreen mode
  • Import CoffeePlan to +page.svelte
<script lang="ts">
import CoffeePlan from '$lib/coffee-plan.svelte';
</script>

<template>
   <div class="content">
      <h1 class="title">Coffee Plans</h1>

      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>

      <div class="plans">
        <CoffeePlan />
        <CoffeePlan />
        <CoffeePlan />
        <CoffeePlan />       
      </div>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Angular 19 application

  • Create a new CoffeePlanComponent
ng g c coffeePlan
Enter fullscreen mode Exit fullscreen mode
@Component({
  selector: 'app-coffee-plan',
  imports: [],
  template: `
    <div class="plan">
        <div class="description">
            <span class="title"> The Single </span>
        </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoffeePlanComponent {}
Enter fullscreen mode Exit fullscreen mode
  • Import CoffeePlanComponent to AppComponent in app.component.ts
import { CoffeePlanComponent } from './coffee-plan/coffee-plan.component';

@Component({
  selector: 'app-root',
  imports: [CoffeePlanComponent],
  template: `
    <div class="content">
      <h1 class="title">Coffee Plans</h1>

      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>

      <div class="plans">
        <app-coffee-plan />
        <app-coffee-plan />
        <app-coffee-plan />
        <app-coffee-plan />
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {}
Enter fullscreen mode Exit fullscreen mode

Add Name Prop to the CoffeePlan Component

Vue 3 application

  • Define a name prop with a default value and proper type. defineProps is automatically imported, so we do not have to import it explicitly.
<script setup lang="ts">
defineProps({
    name: {
        type: String,
        default: 'Default Plan',
    },
})
</script>

<template>
    <div class="plan">
      <div class="description">
        <span class="title"> {{ name }} </span>
      </div>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode
  • Pass Input Values to CoffeePlan Component
<script setup lang="ts">
import CoffeePlan from './components/CoffeePlan.vue'
import { ref } from 'vue'

const plans = ref(["The Single", "The Curious", "The Addict", "The Hacker"])
</script>

<template>
   <div class="content">
      <h1 class="title">Coffee Plans</h1>

      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>

      <div class="plans">
        <CoffeePlan v-for="plan in plans" :key="plan" :name="plan" />
      </div>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

SvelteKit application

  • Define a name prop with a default value and proper type. $props can be used without any import.
<script lang="ts">
interface Props {
    name: string
}

const { name = 'Default Plan'} = $props();
</script>

<div class="plan">
  <div class="description">
    <span class="title">{name}</span>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode
  • Pass Input Values to CoffeePlan Component
<script lang="ts">
import CoffeePlan from '$lib/coffee-plan.svelte';

const plans = $state(['The Single', 'The Curious', 'The Addict', 'The Hacker']);
</script>

<template>
   <div class="content">
      <h1 class="title">Coffee Plans</h1>

      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>

      <div class="plans">
        {#each plans as plan (plan)}
            <CoffeePlan plan={name} />
        {/each}  
      </div>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Angular 19 application

  • Define a name signal input in the CoffeePlanComponent.
@Component({
  selector: 'app-coffee-plan',
  imports: [],
  template: `
    <div class="plan">
        <div class="description">
            <span class="title">{{ name() }}</span>
        </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoffeePlanComponent {
    name = input('Default Plan');
}
Enter fullscreen mode Exit fullscreen mode
  • Pass Input Values to CoffeePlanComponent
import { CoffeePlanComponent } from './coffee-plan/coffee-plan.component';

@Component({
  selector: 'app-root',
  imports: [CoffeePlanComponent],
  template: `
    <div class="content">
      <h1 class="title">Coffee Plans</h1>

      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>

      <div class="plans">
        @for (plan of plans(); track plan) {
            <app-coffee-plan [name]="plan"  />
        }
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
    plans = signal(['The Single', 'The Curious', 'The Addict', 'The Hacker']);
}
Enter fullscreen mode Exit fullscreen mode

We have successfully created a reusable CoffeePlan component and imported it to App component to display different plans.

Github Repositories:

Top comments (0)