aurelia / templating

An extensible HTML templating engine supporting databinding, custom elements, attached behaviors and more.
MIT License
116 stars 103 forks source link

decorating a ViewModel during programmatic composition #297

Closed mbroadst closed 8 years ago

mbroadst commented 8 years ago

I was wondering if it's possible to "decorate" a viewModel with custom methods such that they will be available to the resulting view? Specifically if I had:

my-element.html:

<template><button click.delegate="doSomething()"></template>

my-element.js:

export class MyElement {}

Could I somehow add doSomething to the my-element's viewModel when I'm using either CompositionEngine.createController or CompositionEngine.compose?

Thanks, and sorry for the potentially confusing terminology wrt decoration.

EisenbergEffect commented 8 years ago

Probably there's a way to do what you want...especially in the next release. However, I'm not 100% clear on the scenario.

mbroadst commented 8 years ago

@EisenbergEffect thanks for the quick response. I'm experimenting with a toast component, which is very similar to aurelia-dialog, however I find the implementation of the dialog to be a bit... involved. It seems like there a lot of contortions done there in terms of dynamically injecting a special controller, and that controllers use within the renderer.

The toasts are a far simpler implementation, and at least in the initial implementation do not require the ability to pass in a custom viewModel. I thought it would be very convenient to directly decorate the internally composed component with methods to control the "renderer" during the creation of the component rather than through an injected controller.

Sorry if that description itself is a bit convoluted, I'm trying to mentally work through alternative implementations - so I'm a bit scattered :smile:

EisenbergEffect commented 8 years ago

If you just want to add methods, you can use a decorator to mix in the methods to a class. You probably need some toast service though, which would need to be injected.

I would avoid any sort of "magic" of adding methods to a view model that aren't in some way visible.

mbroadst commented 8 years ago

@EisenbergEffect that's what I'm currently doing, you can see the existing code here: https://github.com/mbroadst/aurelia-toast-demo/tree/master/src/toast

I have a ToastService that dynamically creates a ToastElement and places it into a host (there are six possible positions, so six different toast hosts, this is another issue). This all works quite well, however I need to signal back to the renderer (or really manager) when certain things happen, like a click on the toast itself.

As you can see, this is all derived from aurelia-dialog, however I'm trying to avoid injecting the DialogController and using it the way it's done in that project because:

I was hoping that when I composed the toast-element I could inject the methods needed for interaction with the ToastRenderer at that point.

mbroadst commented 8 years ago

ah it looks like maybe I can do this as part of Controller.automate

EisenbergEffect commented 8 years ago

At your own risk....

EisenbergEffect commented 8 years ago

Note that that is a semi-private api.

mbroadst commented 8 years ago

Are there any other examples of programmatically creating a view + view model and binding data to it (sorry I get this with lifecycle activation) signaling from that element back to a common controller? There seem to be few resources on this, and I'm not sure its clear through the existing documentation what route I should be taking.