Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set_meta operation #117

Merged
merged 2 commits into from
Apr 8, 2021
Merged

set_meta operation #117

merged 2 commits into from
Apr 8, 2021

Conversation

leastbad
Copy link
Contributor

@leastbad leastbad commented Apr 7, 2021

Description

set_meta updates the content of a meta tag in the document head.

If no tag is found, it is created.

Example

Here's a Nothing Reflex that updates a meta tag:

  def meta
    cable_ready.set_meta(name: "pill-messages", content: "5").broadcast
    morph :nothing
  end

Motivation

I've found a really interesting pattern for building UI functionality that makes extensive use of meta tags.

chrome_JV9t4dGYnE

<span class="badge badge-md bg-danger text-white" data-controller="pill" data-pill-tag-value="messages">4</span>

This is all tied together with a Stimulus controller that observes meta tags:

import { Controller } from 'stimulus'

export default class extends Controller {
  static values = { tag: String }

  initialize () {
    this.metaTag = document.head.querySelector(
      `meta[name=pill-${this.tagValue}]`
    )
    this.element.textContent = this.metaTag.content
    this.observer = new MutationObserver(this.meta)
  }

  connect () {
    this.observer.observe(this.metaTag, {
      attributeFilter: ['content']
    })
  }

  disconnect () {
    this.observer.disconnect()
  }

  meta = mutation => {
    const content = mutation[0].target.content
    if (content && content !== '0') {
      this.element.textContent = mutation[0].target.content
      this.element.classList.remove('d-none')
    } else {
      this.element.textContent = ''
      this.element.classList.add('d-none')
    }
  }
}

Basically, any menu items which can feature a notification "pill" observe a meta tag for changes, and update themselves when the meta tag is updated. If there is no content or the content is 0, the pill is hidden.

This is very similar to using set_dataset_property with the Values API, except that it has two advantages:

  • multiple elements can pick up changes from the meta tag, and they don't have to be aware of each other
  • this solution is decoupled from knowing the location of an element in the DOM to receive the dataset property update

Copy link
Contributor

@hopsoft hopsoft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great and will support some interesting use cases.

@leastbad leastbad merged commit aee1d37 into stimulusreflex:master Apr 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants