Component Events

Overview

Components in Now.js provide a robust event handling system that allows you to

Basic Event Handling

DOM Events

Now.getManager('component').define('button-counter', {
  state: {
    count: 0
  },

  methods: {
    handleClick(e) {
      this.state.count++;
    }
  },

  template: `
    <button onclick="methods.handleClick">
      Clicked {{count}} times
    </button>
  `
});

Event Method Context

Event handlers automatically have access to

Event Lifecycle

Mounting Events

Now.getManager('component').define('scroll-watcher', {
  mounted() {
    // Add scroll listener when component mounts
    window.addEventListener('scroll', this.methods.handleScroll);
  },

  beforeDestroy() {
    // Remove scroll listener when component is destroyed
    window.removeEventListener('scroll', this.methods.handleScroll);
  },

  methods: {
    handleScroll(e) {
      // Handle scroll event
    }
  }
});

Event Cleanup

Now.js automatically handles event cleanup when components are destroyed, preventing memory leaks.

Custom Events

Event Emitting

Now.getManager('component').define('custom-form', {
  methods: {
    submitForm(data) {
      // Emit custom event
      this.emit('form:submit', {
        data,
        timestamp: Date.now()
      });
    }
  }
});

Event Listening

Now.getManager('component').define('form-handler', {
  mounted() {
    // Listen for custom event
    this.on('form:submit', this.methods.handleSubmit);
  },

  methods: {
    handleSubmit(e) {
      const { data, timestamp } = e.detail;
      // Handle form submission
    }
  }
});

Event Delegation

Now.js supports efficient event delegation for handling multiple similar elements

Now.getManager('component').define('todo-list', {
  template: `
    <ul onclick="methods.handleClick" class="todo-list">
      {{#each items}}
        <li data-id="{{id}}">{{text}}</li>
      {{/each}}
    </ul>
  `,

  methods: {
    handleClick(e) {
      const item = e.target.closest('li');
      if (item) {
        const id = item.dataset.id;
        // Handle item click
      }
    }
  }
});

Performance Optimization

Event Debouncing

Now.getManager('component').define('search-input', {
  mounted() {
    this.debouncedSearch = this.debounce(
      this.methods.performSearch,
      300
    );
  },

  methods: {
    handleInput(e) {
      this.debouncedSearch(e.target.value);
    },

    performSearch(query) {
      // Actual search implementation
    }
  }
});

Event Throttling

Now.getManager('component').define('infinite-scroll', {
  mounted() {
    this.throttledScroll = this.throttle(
      this.methods.checkScroll,
      100
    );
    window.addEventListener('scroll', this.throttledScroll);
  },

  methods: {
    checkScroll() {
      // Load more content logic
    }
  }
});

Event Utilities

Stopping Event Propagation

methods: {
  handleClick(e) {
    e.stopPropagation();
    // Handle click without bubbling
  }
}

Preventing Default Behavior

methods: {
  handleSubmit(e) {
    e.preventDefault();
    // Custom form handling
  }
}

Best Practices

API Reference

Event Methods

on(event, handler)
Add event listener
off(event, handler)
Remove event listener
emit(event, data)
Emit custom event
debounce(fn, wait)
Create debounced function
throttle(fn, limit)
Create throttled function

Event Properties

event.detail
Custom event data
event.target
Event target element
event.currentTarget
Current event target

Examples

Form Handling

Now.getManager('component').define('login-form', {
  template: `
    <form onsubmit="methods.handleSubmit">
      <input type="text" name="username" onchange="methods.handleInput">
      <input type="password" name="password" onchange="methods.handleInput">
      <button type="submit">Login</button>
    </form>
  `,

  state: {
    formData: {}
  },

  methods: {
    handleInput(e) {
      this.state.formData[e.target.name] = e.target.value;
    },

    handleSubmit(e) {
      e.preventDefault();
      this.emit('login:attempt', this.state.formData);
    }
  }
});

Custom Event Communication

// Parent component
Now.getManager('component').define('message-app', {
  mounted() {
    this.on('message:send', this.methods.handleMessageSend);
  },

  methods: {
    handleMessageSend(e) {
      const message = e.detail;
      // Handle message sending
    }
  }
});

// Child component
Now.getManager('component').define('message-input', {
  methods: {
    sendMessage(text) {
      this.emit('message:send', {
        text,
        timestamp: Date.now()
      });
    }
  }
});

Troubleshooting

Common Issues

Solutions

Next Steps