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

How to migrate inline HB-helpers #9

Open
evil-shrike opened this issue May 25, 2018 · 5 comments
Open

How to migrate inline HB-helpers #9

evil-shrike opened this issue May 25, 2018 · 5 comments

Comments

@evil-shrike
Copy link

I have a HB helper, let's call data-bind. It's being used as:

<input {{data-bind name="value" prop="myprop"}}>

it creates two-way data-binding between an DOM-element and an object. During template execution it return html string. Like " id='x1' ". So the above code become <input id='x1'>. It allows later after template executed and its html inserted into DOM find the element and initialize binding.
I understand that with incremeanl-dom two-way binding can be unneeded. But it's just an example of such a helper.
So I'm trying to understand what helper should return in case of ibars backend.
At first attempt I just tried to call: IncrementalDOM.attr("id", <generated_id>); in my helper. But it does nothing.
In debugger I can see generated template 's code as:

IncrementalDOM.elementOpen("div", "idom-430", null, ""
    + (helpers['data-bind'] || (depth0 && HBX.get(depth0, 'data-bind')) || helpers.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"data-bind","hash":{"prop":"myprop","name":"value",},"data":data})
    + "", ""))

So after my helper returned then IncrementalDOM.elementOpen is called with "undefined" in its last argument. Like: IncrementalDOM.elementOpen("div", "idom-430", null, "undefined")
So ibars expects that helper returns a string for a single attr name. No more.
But the last argument of elementOpen according to the docs is a dynamic list like ...args - http://google.github.io/incremental-dom/#api/elementOpen
It seems logically to support returning an array and convert it into method's args.

Anyway what would be a possible workaround for such a case? What should helper return?

It's mentioned in READ that:

It is however totally possible to create an ad-hoc 'attribute' helper that does that directly on the DOM element. This is again something I never do as in my opionion returning html artifacts from templates smells of anti-pattern.

How such ad-hoc helper could be implemented?

@evil-shrike
Copy link
Author

Let me add one more example

Givien a template:

<input {{data-bind value="myprop" }} />

Emitter returns:

"(IncrementalDOM.elementVoid("input", "idom-4", null, ""{{data-bind value="myprop"}}"", ""))"

After that Handlebars compiler processes and expand helpers into the following template function:

(function anonymous(container,depth0,helpers,partials,data
) {
  return (IncrementalDOM.elementVoid("input", "idom-4", null, ""
    + (helpers['data-bind'] || (depth0 && HBX.get(depth0, 'data-bind')) || helpers.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"data-bind","hash":{"value":"myprop"},"data":data})
    + "", ""));
})

What I was thinking about is that emiiter should not wrap a helper call into quotes. Instead it could construct an array like this:

(IncrementalDOM.elementVoid.apply(null,["input", "idom-4", null].concat( {{data-bind value="myprop"}} || []) )

then helper could return an array like ["id", "x1"] and it will be passed into elementVoid.
At the end we'll get a call like IncrementalDOM.elementVoid.apply(null,["input", "idom-4", null, "id", "x1"]. So that helpers will be able to pass arbitrary attr and their values into idom.

@atomictag
Copy link
Owner

atomictag commented Jun 1, 2018 via email

@evil-shrike
Copy link
Author

Ok. Can I ask you how do you add event handlers for html elements? Handlebars itself doesn't have a notion of event handlers, helpers can't access dom nor vdom so they also can't add handlers. So what are options do you have? Just manually subscribe after patch?

@atomictag
Copy link
Owner

atomictag commented Jun 1, 2018 via email

@evil-shrike
Copy link
Author

Such a callback would be called for every element right? But how can I tell from my template that for a particular button I need a click handler? I'd need to store some meta info and current context on a element and then later in that onOpen callback find them and subscribe to appropriate event. But we don't have any access to element in helpers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants