WebReflection / hyperHTML

A Fast & Light Virtual DOM Alternative
ISC License
3.07k stars 113 forks source link

Invokable Slot #282

Closed WebReflection closed 6 years ago

WebReflection commented 6 years ago

There are a variety of use cases for having a callback invoked while the node content is being populated.

Even if I am sure this opportunity will be most likely misused, it might simplify intent-like use cases in scope, also providing a parent node reference for weakly related composition (i.e. the possibility of automating hyperHTML.Component in JSX like syntax).

coveralls commented 6 years ago

Pull Request Test Coverage Report for Build 668


Totals Coverage Status
Change from base Build 667: 0.0%
Covered Lines:
Relevant Lines: 0

💛 - Coveralls
bigopon commented 6 years ago

@WebReflection This sounds nice. May I know motivation for this and see some examples?

WebReflection commented 6 years ago

@bigopon more than once developers asked me a way to know which node was getting rendered, and indeed there is no way if not using an attribute intent so that such node, as soon as opened, would be passed along.

However, nested elements could never know without some DOM hackery where these are going to be rendered, and there's no way to relate hyper.Component if transformed.

The latter one is necessary for cases where you write JSX:

const { Component, bind } = hyperHTML;

class Rando extends Component {
  render() {
    return this.html(
      <Sub value={1 + this.props.rand} />
      <Sub value={2 + this.props.rand} />
    );
  }
}

class Sub extends Component {
  render() {
    return this.html(
      <div>
        Value <strong>{this.props.value}</strong>
      </div>
    );
  }
}

const render = bind(document.body);
render(
  <div>
    <Rando rand={Math.random()} />
  </div>
);

and you'd like to have this transformation:

const { Component, bind } = hyperHTML;

class Rando extends Component {
  render() {
    return this.html`
      ${parent => {
        const comp = Sub.for(parent, 1);
        comp.props = {value: 1 + this.props.rand};
        return comp;
      }}
      ${parent => {
        const comp = Sub.for(parent, 2);
        comp.props = {value: 2 + this.props.rand};
        return comp;
      }}
    `;
  }
}

class Sub extends Component {
  render() {
    return this.html`
      <div>
        Value <strong>${this.props.value}</strong>
      </div
    `;
  }
}

const render = bind(document.body);
render`
  <div>
    ${parent => {
      const comp = Rando.for(parent, 1);
      comp.props = {rand: Math.random()};
      return comp;
    }}
  </div>
`;

Which makes light Components way more useful / Reactish, if/when needed.

Although this is just theoretical, 'cause I need to get this done first, but it exposes a super important detail that would make it otherwise impossible to grab without ugly work-arounds.