Component Communication

Overview

Now.js provides several methods for components to communicate with each other

Parent to Child Communication

Using Props

The most basic form of component communication is passing props from parent to child

Parent Component

Now.getManager('component').define('user-list', {
  template: `
    <div class="user-list">
      <user-card
        data-prop-user="{{user}}"
        data-prop-show-details="true"
        data-json-prop-actions="{{actions}}">
      </user-card>
    </div>
  `,
  state: {
    user: {
      name: 'John Doe',
      email: 'john@example.com'
    },
    actions: {
      edit: () => console.log('edit'),
      delete: () => console.log('delete')
    }
  }
});

Child Component

Now.getManager('component').define('user-card', {
  template: `
    <div class="user-card">
      <h3>{{props.user.name}}</h3>
      {{#if props.showDetails}}
        <p>{{props.user.email}}</p>
      {{/if}}
      <div class="actions">
        <button onclick="{{props.actions.edit}}">Edit</button>
        <button onclick="{{props.actions.delete}}">Delete</button>
      </div>
    </div>
  `,
  props: {
    user: null,
    showDetails: false,
    actions: {}
  }
});

Child to Parent Communication

Using Events

Children can communicate with parents by emitting events

Child Component

Now.getManager('component').define('user-card', {
  methods: {
    handleEdit() {
      // Emit event to parent
      this.emit('user:edit', {
        userId: this.props.user.id
      });
    }
  },
  template: `
    <div class="user-card">
      <button onclick="methods.handleEdit">Edit</button>
    </div>
  `
});

Parent Component

Now.getManager('component').define('user-list', {
  mounted() {
    // Listen for child events
    this.on('user:edit', (event) => {
      console.log('Edit user:', event.detail.userId);
    });
  }
});

Global Communication

Using Event Manager

Components can communicate globally using the EventManager

// Component A
Now.getManager('component').define('component-a', {
  methods: {
    broadcastMessage() {
      Now.getManager('event').emit('global:message', {
        text: 'Hello from Component A'
      });
    }
  }
});

// Component B
Now.getManager('component').define('component-b', {
  mounted() {
    Now.getManager('event').on('global:message', (event) => {
      console.log('Received:', event.data.text);
    });
  }
});

Using State Manager

Share and sync state between components

// Define shared state
const stateManager = Now.getManager('state');
stateManager.registerModule('users', {
  state: {
    currentUser: null,
    userList: []
  },
  mutations: {
    setCurrentUser(state, user) {
      state.currentUser = user;
    }
  }
});

// Component A - Updates state
Now.getManager('component').define('user-selector', {
  methods: {
    selectUser(user) {
      stateManager.commit('users/setCurrentUser', user);
    }
  }
});

// Component B - Reacts to state changes
Now.getManager('component').define('user-profile', {
  mounted() {
    stateManager.watch('users/currentUser', (user) => {
      this.state.displayedUser = user;
    });
  }
});

Component References

Access child components directly using refs

Now.getManager('component').define('form-container', {
  template: `
    <form>
      <input-field data-ref="emailInput"></input-field>
      <button onclick="methods.submit">Submit</button>
    </form>
  `,
  methods: {
    submit() {
      // Access child component directly
      const email = this.refs.emailInput.getValue();
      console.log('Email:', email);
    }
  }
});

Best Practices

Performance Considerations

Common Patterns

Mediator Pattern

// Create a mediator component
Now.getManager('component').define('chat-mediator', {
  mounted() {
    // Handle messages between components
    this.on('message:send', (event) => {
      this.state.messages.push(event.detail);
      this.emit('message:received', event.detail);
    });
  }
});

Observer Pattern

// Create observable state
const userStore = {
  observers: new Set(),
  user: null,

  setUser(user) {
    this.user = user;
    this.notifyObservers();
  },

  addObserver(component) {
    this.observers.add(component);
  },

  notifyObservers() {
    this.observers.forEach(component => {
      component.onUserChange(this.user);
    });
  }
};

Troubleshooting

Common Issues

Debugging Tips

Next Steps