question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Declarative view events

See original GitHub issue

What is the recommended way to pass events through a declarative view?

vw(CustomerSelector, {
  _events: {
    select: customer => console.log('I am never called from vm.emit')
  }
}),
vw(CustomerSelector, {
  onselect: customer => console.log('Do I put this in the model?')
}, 'key-needed-else-always-remounts'),

Sometimes I use a global state object or sometimes I will pass a model for the view to manipulate vw(CustomerSelector, OrderForm) but there are times when I’d prefer a component that only knows about it’s internal state and abstracts underlying input events and exposes it’s own set of event handlers.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:16 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
leeoniyacommented, May 24, 2017

Due to layout limitations, you sometimes cannot have a conceptually related element as a child, or even a sibling.

this was actually a core consideration during domvm’s design. the conclusion i came to after multiple prototypes is that the least-surprises route is simply not to use declarative views in cases like this. and so, this need is addressed in domvm by imperative view composition, which, i think, is domvm’s distinguishing feature; you can inject pre-initialized, partial views into disjoint parts of your templates (or dom mount points) while maintaining isolated redraw control without relying on a global shared state and global redraw.

var el = domvm.defineElement,
    iv = domvm.injectView;

function Dropdown(opts) {
    function InputView() {
        return () =>
            el("input");
    }

    function OptsView() {
        return () =>
            el("ul", opts.map(o =>
                el("li", o)
            ));
    }
    
    // public api and exposed views for embedding
    const self = {
        open: () => {/*...*/},
        close: () => {/*...*/},
        redraw: () => {
            for (var name in self.views)
                self.views[name].redraw();
        },
        views: {
            input: domvm.createView(InputView, self),
            opts: domvm.createView(OptsView, self),
        },
    };
    
    return self;
}

function AppView(vm, state) {
    const myDrop = Dropdown(["A","B","C"]);
    
    return () =>
        el("body", [
            el("header", [
                "Hello...",
                iv(myDrop.views.input),
            ]),
            el("main", [
                "Options: ",
                iv(myDrop.views.opts),
            ])
        ]);
}

var appView = domvm.createView(AppView).mount(document.body, true);

by giving up declarative view composition, you get shared state without hacks, disjoint and granular redraw control, a user-defined exposed widget API/state. the second example of https://github.com/leeoniya/domvm#hello-world is somewhat like this but exposes a single view from the “component”. there’s also wiki page (that needs updating to domvm v2) on the flexibility of different patterns. (v1 had JSONML-esque templates, but the semantics remained the same).

anyways, hope that helps or gives you some ideas. regardless, if you found something that works/makes sense for you then go with it 😃

[1] https://github.com/leeoniya/domvm/wiki/View-Model-Patterns

1reaction
leeoniyacommented, May 19, 2017

there’s no requirement for the wrapper to have a model key, it’s just an example. domvm doesnt care about anything except the identity of the object you pass in and the key. you can have a wrapper {someState: foo, myEvents25: ...} and it’ll work fine.

the only place where the literal model exists is vm.model, which you dont ever need to reference because it’s passed into the view closure and render() as an arg, and you can rename that to “state” in your app code if you prefer.

if you’re talking more from a documentation / philosophical perspective, i think that “model” is a better fit for domvm since it doesnt advertise itself as a pure/functional solution, though it can easily be used this way by simply ignoring the view closure state and only ever using the args passed to render(). pure functional solutions frequently have to jump through a lot of hoops because having granular state is a pretty useful thing.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Difference between declarative and imperative in React.js?
A declarative style, like what react has, allows you to control flow and state in your application by saying "It should look like...
Read more >
Declarative Action Event Mapping | ServiceNow Developer
Declarative actions are a scriptless way to use events to add custom functionality to forms, fields, lists, and other components.
Read more >
Declarative Event-Oriented Programming - Microsoft Research
We propose a declarative approach to event-oriented programming, based on a powerfully expressive event language with a lightweight notation. We ...
Read more >
Declarative Views - Cocoa with Love
In this article, I'll look at the the biggest problem with non-declarative views and how frameworks have slowly become more declarative, ...
Read more >
8 steps to turn imperative JavaScript class to a functional ...
As an example we will take JavaScript code to create event manager adding ... to show you options of how the worlds of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found