Hone logo
Hone
Problems

Vue Component Event Emission

In Vue.js, components communicate with their parent components primarily through events. This challenge focuses on implementing the mechanism for a child component to emit custom events that its parent can listen to and react to. This is a fundamental aspect of building reusable and interactive Vue components.

Problem Description

You are tasked with creating a Vue child component that can emit custom events with associated data to its parent. The parent component will then listen for these events and update its own state or perform actions based on the received data.

Key Requirements:

  1. Child Component (EventEmitter.vue):

    • Must accept a prop message (string) which it will display.
    • Must have a button. When this button is clicked, it should emit a custom event named custom-message.
    • The custom-message event should carry the message prop's value as its payload.
    • The component should also have another button that, when clicked, emits a simple event named notify without any payload.
  2. Parent Component (App.vue):

    • Must render the EventEmitter child component.
    • Must pass a string value to the message prop of the EventEmitter component.
    • Must listen for the custom-message event emitted by the child. When this event is received, it should update a local data property called receivedMessage.
    • Must listen for the notify event emitted by the child. When this event is received, it should toggle a boolean data property called notificationActive.

Expected Behavior:

  • When the EventEmitter component displays, the message passed via props should be visible.
  • Clicking the button in EventEmitter that sends the custom-message should update the receivedMessage in the App component with the message that was displayed in the child.
  • Clicking the button in EventEmitter that sends the notify event should toggle the notificationActive state in the App component (e.g., from false to true, then true to false).
  • The App component should visually indicate the status of notificationActive (e.g., by displaying text like "Notification is ON" or "Notification is OFF").

Edge Cases to Consider:

  • The initial state of receivedMessage should be an empty string.
  • The initial state of notificationActive should be false.

Examples

Example 1:

Child Component (EventEmitter.vue) Template:

<div>
  <p>Message from parent: {{ message }}</p>
  <button @click="$emit('custom-message', message)">Send Custom Message</button>
  <button @click="$emit('notify')">Notify Parent</button>
</div>

Child Component (EventEmitter.vue) Script (TypeScript):

import { defineComponent } from 'vue';

export default defineComponent({
  props: {
    message: {
      type: String,
      required: true,
    },
  },
  // No explicit emits declaration required for this basic case with <script setup>
  // but for clarity in a traditional <script> tag, you might declare:
  // emits: ['custom-message', 'notify']
});

Parent Component (App.vue) Template:

<div>
  <h1>Parent Component</h1>
  <EventEmitter
    :message="parentMessage"
    @custom-message="handleCustomMessage"
    @notify="toggleNotification"
  />
  <p>Received Message: {{ receivedMessage }}</p>
  <p>Notification Status: {{ notificationActive ? 'ON' : 'OFF' }}</p>
</div>

Parent Component (App.vue) Script (TypeScript):

import { defineComponent, ref } from 'vue';
import EventEmitter from './components/EventEmitter.vue';

export default defineComponent({
  components: {
    EventEmitter,
  },
  setup() {
    const parentMessage = ref('Hello from App!');
    const receivedMessage = ref('');
    const notificationActive = ref(false);

    const handleCustomMessage = (msg: string) => {
      receivedMessage.value = msg;
    };

    const toggleNotification = () => {
      notificationActive.value = !notificationActive.value;
    };

    return {
      parentMessage,
      receivedMessage,
      notificationActive,
      handleCustomMessage,
      toggleNotification,
    };
  },
});

Explanation:

The EventEmitter component displays "Message from parent: Hello from App!". When the "Send Custom Message" button is clicked, it emits custom-message with "Hello from App!" as data. The App component receives this, and handleCustomMessage sets receivedMessage to "Hello from App!". When the "Notify Parent" button is clicked, it emits notify. The App component receives this, and toggleNotification flips notificationActive from false to true. The displayed "Notification Status" will update accordingly.

Constraints

  • You must use Vue 3 with the Composition API and TypeScript.
  • The EventEmitter.vue component should be structured using <script setup> for conciseness, but it's crucial to understand how emits work conceptually.
  • The App.vue component should use the <script> tag with setup() function.
  • The message prop in EventEmitter.vue must be declared with type: String and required: true.
  • The data properties in App.vue (receivedMessage, notificationActive) should be initialized as specified.

Notes

  • When using <script setup>, the $emit function is implicitly available. However, for clarity and best practice in larger applications or with the Options API, you would typically declare the emitted events using the emits option.
  • Consider how you would structure your emits declaration if you were not using <script setup> to explicitly define the event names and their payloads. This is a good learning point for understanding explicit event definitions.
  • The goal is to demonstrate a clear parent-child communication flow using custom events.
Loading editor...
typescript