Nice read, got me laughing in the middle That pretty much explains the ~300% productivity boost Iāve been experiencing lately. Very thankful for having ViewModel.
Out of curiosity, have you tried migrating an app built with the Blaze version of ViewModel to React? It seems like there could almost be an automated tool for it, theyāre so similar. Where would the biggest bulk of manual labour be lurking?
Iām rewriting the phone book example with viewmodel-react. Itās very easy to translate one to another but I donāt think itās worth it to create a converter because there are a lot of non-ViewModel edge cases where Blaze behaves one way and React another. I donāt know of anyone who writes 100% idiomatic ViewModel (not even myself) so thereās some translation to do.
While that is certainly nice, the documentation is a bit sparse on the āAnd how do I actually get data in there?ā part.
Basically, itās missing quite an important piece of the āModelā in āViewModelā.
Just thought you should know that prior to VM for React, I could not consider even using React as it wasnāt quite as productive as what I was able to achieve with Blaze/VM (and productivity is my #1 concern as we are a small team).
Yet the React VM makes it completely viable for my purposes - and sometimes the code actually ends up being even cleaner than the Blaze alternative. So now we are using React for new projects, and we are seriously considering switching over our very large business app to React in the future (which is a big deal - we have not even upgraded for 1.4/import statements/etc yet - not worth our time - so for us to consider this upgrade means a lot!).
Thank you very much for your work!
I need to explain this better in the documentation.
-
This is just the V in MVC. It has little to do with your DB models. Itās called view-model because itās a pair, the view is rendered based on a model (the āmodel of the viewā). Itās not the capital M in MVC. For example, if you have the view-model
<div b="text: message" />
-{ message: "Hello" }
then you know the view will render<div>Hello</div>
. The view always renders based on its model. -
You load data the same way you would with any other view layer. With the old Meteor you can just return the results of a collection in a method. For one time data you populate your collection when the components are created. With something like Horizon/RethinkDB you subscribe to the data stream:
const Horizon = require('@horizon/client');
const horizon = Horizon({ secure: false });
const messagesCollection = horizon('messages');
Messages({
created() {
messagesCollection.watch().subscribe(
(messages) => { this.messages(messages);}
);
},
messages: [],
render() {
<div>
Messages:
<Message b="repeat: messages" />
</div>
}
})
This is on my todo-list
Ah, its that thing!
I think its wonderful, but really, nearly the only reason why people work with React - because everyone does.
Thatās the reason most people are careful about switching into different āsugarā until its stable and recommended by tons of different manuals and blogsā¦
Yet, I feel that ViewModel, its documentation and github responses are just insane, I donāt remember that much love put into project except redux itself, hence its popularity. Will think about switching to ViewModel again, but anyway, Viewmodel docs and github are pure candy for my exhausted eyes!
And just for that I changed the code samples from Kansas black and white to Technicolor
Random thoughts (sorry, I have many)ā¦
I disagree a lot with DHH (who created Ruby on Rails) but I wholeheartedly agree with his sentiment surrounding design decisions or RoR. For example, like RoR, ViewModel optimizes for developer happiness. Whoās happiness? First and foremost, mine. If it sounds selfish, itās because it is. I want to smile when I see my code, and I do smile when I look at something like this:
List({
colors: ['red', 'green', 'blue'],
render(){
<ul>
<li b="repeat: colors, text: repeatObject, style: { color: repeatObject }" />
</ul>
}
})
A lot of people see that and scoff āToo much magic!āā¦ ViewModel isnāt for them.
Some people look at that and they smile with me thinking āThat is the absolute minimum way to express what I want to do.āā¦ ViewModel is for them.
As long as you donāt go down the āMust monkeypatch everything!ā route like RoR did
Because too much magic can make it very difficult to override behaviours when you need to.
Another question: How well does it play with other React components?
Say, I want to use MaterialUI - Iām seeing bindings for the standard attributes, what about custom ones, like:
<Dialog
title="Dialog With Actions"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
Would I be able to bind, say, title
to a ViewModel?
Sure,
Example({
title: "Dialog With Actions",
render(){
<Dialog title={this.title()} />
}
})
Although it looks innocuous, {this.title()}
starts getting annoying when youāre dealing with a lot of attributes (e.g. youāre working with SVG). ViewModel has the option of specifying which attributes should be used as binding. Then you can do:
Example({
title: "Dialog With Actions",
render(){
<Dialog b="title: title" />
}
})
Is this open source? Where is the source code? I canāt find any github link
Amazing the things you forget to include in the docs.
Look like you extracting Tracker from Meteor. Why donāt you publish it as separate NPM package?
Last question, is this possible to render HTML directly?
With JSX, we use dangerouslySetInnerHTML
which is inconvenient.
It would be great to have a simple example also for meteorā¦ for noob like me!
I use a copy of Tracker because I removed all Meteor references from it. I donāt publish it on NPM because 1) I honestly donāt see the point and 2) I donāt want to maintain it (be the person who answers questions about Tracker).
As for direct HTML, see https://viewmodel.org/#BindingsHtml
Example({
message: 'Can it be a <strike>strike</strike>?',
render() {
<div>
<input b="value: message" placeholder="Type something" />
<label b="html: message" />
</div>
}
})
I know that. What I asked, suppose I have input html string:
let html = `<p>I'm html <strong>string</strong></p>`
Can I render that like so:
render() {
return (
<div>
{html}
</div>
)
}
That is exactly what it does.