Skip to content

useTargetMutation

useTargetMutation tracks when targets are added, updated and removed to your controller.

!> Deprecated: [target]TargetAdded and [target]TargetRemoved are deprecated. Please use the built-in [target]TargetConnected() and [target]TargetDisconnected() functions from Stimulus: https://stimulus.hotwired.dev/reference/targets#connected-and-disconnected-callbacks

It adds three new behaviors to your Stimulus controller for each target you specify:

  • [target]TargetAdded triggered when targets get added to your controller, either by adding the target attribute to an existing element in the controller's scope, or by adding a new element with those attributes to the controller's scope.
  • [target]TargetRemoved triggered when targets get removed from your controller, either by removing the target attribute from an existing element in the controller's scope, or by removing an existing element with those attributes to the controller's scope.
  • [target]TargetChanged triggered when the contents of a target change, adding text/elements to its subtree.

[target]TargetAdded, [target]TargetRemoved, and [target]TargetChanged only receive one parameter, the target node that was added, removed, or changed.

Reference

javascript
useTargetMutation(controller, options)

controller : a Stimulus Controller (usually 'this')

options :

OptionDescription           Default value               
debugWhether to log debug information. See debug for more information on the debugging toolsfalse
targetsAn array of target names to track for mutationsall targets
js
export default class extends Controller {

  static targets = ["location", "content", "view"]

  connect() {
    useTargetMutation(this)
  }

  locationTargetAdded(element) {
    console.log('A new location was added!')
  }

  locationTargetRemoved(element) {
    console.log('A location was removed!')
  }

  locationTargetChanged(element) {
    console.log('A location was changed!')
  }

  contentTargetAdded(element) {
    console.log('A content target was added!')
  }

  contentTargetRemoved(element) {
    console.log('A content target was removed!')
  }

  contentTargetChanged(element) {
    console.log('A content target was changed!')
  }

  viewTargetAdded(element) {
    console.log('A view target was added!')
  }

  viewTargetRemoved(element) {
    console.log('A view target was removed!')
  }

  viewTargetChanged(element) {
    console.log('A view target was changed!')
  }

}

Usage

Composing

js
import { Controller } from '@hotwired/stimulus'
import { useTargetMutation } from 'stimulus-use'

export default class extends Controller {

  static targets = ["location", "content", "view"];

  connect() {
    useTargetMutation(this, { targets: ["location"] }) // only track mutations of "location" target
  }

  locationTargetAdded(element) {
    // triggered when a locationTarget is added
  }

  locationTargetRemoved(element) {
    // triggered when a locationTarget is removed
  }

  locationTargetChanged(element) {
    // triggered when a locationTarget is changed
  }

}

Extending a controller

js
import { TargetMutationController } from 'stimulus-use'

export default class extends TargetMutationController {

  static targets = ["location"]

  locationTargetAdded(element) {
    // triggered when a locationTarget is added
  }

  locationTargetRemoved(element) {
    // triggered when a locationTarget is removed
  }

  locationTargetChanged(element) {
    // triggered when a locationTarget is changed
  }

}

Extending a controller with options

js
import { TargetMutationController } from 'stimulus-use'

export default class extends TargetMutationController {

  static targets = ["location", "view", "content"]
  static options = { targets: ["location"] }

  locationTargetAdded(element) {
    // triggered when a locationTarget is added
  }

  locationTargetRemoved(element) {
    // triggered when a locationTarget is removed
  }

  locationTargetChanged(element) {
    // triggered when a locationTarget is changed
  }

}

Controlling observation

useTargetMutation returns an [observe, unobserve] tuple so you can start and stop observing manually. Observation starts automatically when the mixin is called and is cleaned up automatically when the controller disconnects. When extending TargetMutationController, the same functions are available as this.observe() and this.unobserve().

js
connect() {
  const [observe, unobserve] = useTargetMutation(this)
  // later: unobserve() to pause, observe() to resume
}