linkedin / dustjs

Asynchronous Javascript templating for the browser and server
http://dustjs.com
MIT License
2.91k stars 478 forks source link

Add support for non-plain-object models #725

Open cleverplatypus opened 8 years ago

cleverplatypus commented 8 years ago

Dust takes for granted that the objects passed as models are plain native objects, i.e. Object, Array, String, Number etc.

In some applications, the model is represented by custom objects that expose accessors to read properties. This is mainly done to support data binding and observers that don't use the deprecated Object.observe API, e.g. EmberJS/SproutCore's model objects. I have my custom UI library that uses exactly this approach exposing in ObservableObject, ObservableCollection the .prop() method to read/write property/path values: e.g.

myObservableObject.prop('my.path.to.string') //read
myObservableObject.prop('my.path.to.string', 'new value') //write

Other templating libraries, like Handlebars, allow the extension of the renderer's properties access method. It would be great seeing this piece of functionality implemented in dustjs, with some form of delegation.

At the moment, I'm brutally embedding the desired logic in the dust.js file, in my fork.

Cheers

sethkinast commented 8 years ago

You're just dumping something into Context#_get?

cleverplatypus commented 8 years ago

something like that, yes. appalling, I know. I'm in the middle of testing my framework and dust is plugged in for the templating side. It's working, so the hack is fine for the time being, as I didn't have the time to extend dust properly, but it's clearly not the way to go, is it? :)

sethkinast commented 8 years ago

To clarify, you'd basically like a default implementation of get(key) that you can override as you'd like?

cleverplatypus commented 8 years ago

Correct. Let's say something like this:

dust.dataResolver = function(context, path) {
   return context.prop(path);
}

where the default dust.dataResolver is the current dust implementation.

There also should be some kind of delegation for iterating over collections as in

{#company.people}
{first_name}
{/company.people}
cleverplatypus commented 8 years ago

A use case for the iteration feature is an object that implements the ES6 [Symbol.iterator] protocol

cleverplatypus commented 8 years ago

@sethkinast Did you have a chance to think about this feature req?

sethkinast commented 8 years ago

I won't have time to get to it soon, PR welcome. Otherwise, it's on my mind :)

cleverplatypus commented 8 years ago

Hey Seth. Thanks for getting back to me on this.

I don't have full understanding of the inner workings of dustjs, therefore any submitted code would be inadequately implemented. I might get support from the community.

N.

On 5 May 2016 at 04:51, Seth Kinast notifications@github.com wrote:

I won't have time to get to it soon, PR welcome. Otherwise, it's on my mind :)

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/linkedin/dustjs/issues/725#issuecomment-216972584

sethkinast commented 8 years ago

No problem, will investigate it in the future :)

On Thu, May 5, 2016 at 3:29 PM aekidna notifications@github.com wrote:

Hey Seth. Thanks for getting back to me on this.

I don't have full understanding of the inner workings of dustjs, therefore any submitted code would be inadequately implemented. I might get support from the community.

N.

On 5 May 2016 at 04:51, Seth Kinast notifications@github.com wrote:

I won't have time to get to it soon, PR welcome. Otherwise, it's on my mind :)

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/linkedin/dustjs/issues/725#issuecomment-216972584

— You are receiving this because you were mentioned.

Reply to this email directly or view it on GitHub https://github.com/linkedin/dustjs/issues/725#issuecomment-217298270

cleverplatypus commented 8 years ago

Aw, forgot to ask. Would you mind tagging this a feature-request? Cheers

On 6 May 2016 at 08:00, Seth Kinast notifications@github.com wrote:

No problem, will investigate it in the future :)

On Thu, May 5, 2016 at 3:29 PM aekidna notifications@github.com wrote:

Hey Seth. Thanks for getting back to me on this.

I don't have full understanding of the inner workings of dustjs, therefore any submitted code would be inadequately implemented. I might get support from the community.

N.

On 5 May 2016 at 04:51, Seth Kinast notifications@github.com wrote:

I won't have time to get to it soon, PR welcome. Otherwise, it's on my mind :)

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/linkedin/dustjs/issues/725#issuecomment-216972584

— You are receiving this because you were mentioned.

Reply to this email directly or view it on GitHub https://github.com/linkedin/dustjs/issues/725#issuecomment-217298270

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/linkedin/dustjs/issues/725#issuecomment-217298461

pantaluna commented 8 years ago

@sethkinast Would this feature request also include support for ES6 Maps? I cannot get ES6 Maps to work right now for obvious reasons. A map is always considered {} in the Context. What I'm doing right now is creating an extra object in the Context for each Map element of the input data but that is not an optimal solution.

cleverplatypus commented 8 years ago

@pantaluna That would be the proposed idea, supporting dictionaries/collections that cannot be natively enumerated, i.e. don't expose the values through own-properties.

The extra object you're creating for your maps points out exactly the performance problem I was trying to avoid. My ObservableObject can be turned into regular Object/Array instance by calling the .toNative() method. Calling it just before rendering wouldn't be a big problem in the case of, say, a reasonably sized array of strings. But if we're passing a complex object to the context like an array of products, the whole tree would have to be (deeply) turned into a native structure wasting computing time and memory, even if we're rendering only a few properties of each collection item.

Handlebars supports this object translation functionality via, if I remember correctly, decorators. EmberJS and SproutCore extend Handlebars to support their own data object model.