marko-js-archive / marko-widgets

[LEGACY] Module to support binding of behavior to rendered UI components rendered on the server or client
http://v3.markojs.com/docs/marko-widgets/
MIT License
141 stars 40 forks source link

Make state property full reactively #172

Open StarpTech opened 7 years ago

StarpTech commented 7 years ago

New Feature

Make state object full reactively with getters and setters.

Description

I want to create a form component which consists of different html elements. This form state can be very complex. At the moment the state property is only reactive on the first level. You can set the state as dirty setStateDirty('x') but this can affect other DOM elements in the components which dont rely on that state and this can lead to perfomance degradation. In my opinion a template engine should not enforce you how your data looks like. You should be flexible. At the moment you can use prefixed porpertys like this.state.formFieldPassword to hold my state flat with binding but this is not elegant. The state should be the single source of truth to ensure that any mutation can also be rendered on server side. At the moment I can see the trend that state derivates are created by DOM libarys because the concept of the state property is not clear enough.

Context

class {
    onInput(input) {
        this.state = {
            form: {
                test: 'foo',
                fields: { password: { hasError: false  } }
            }
        };
    }
    passwordChange(event) {

        // has no impact
        this.state.form.test = 'bar'

    }
}

<form onSubmit('handleSubmit') class="form-horizontal">
    <div class="form-group" class={ 'has-error': state.form.fields.password.hasError, 'form-group': true }>
        <label for="inputPassword" class="col-sm-2 control-label">Password</label>
        <div class="col-sm-10">
        <input onChange('passwordChange') type="password" class="form-control" id="inputPassword" placeholder="Password">
        <span id="helpBlock2" class="help-block">${state.form.test}</span>
        </div>
    </div>
</form>

Possible Implementation

Walk through all of state properties and convert them to getter/settersusing Object.defineProperty.

https://vuejs.org/v2/api/#data https://vuejs.org/v2/guide/reactivity.html

Open Questions

When this approach don't matched with the design what is the approach to handle complex states?

Is this something you're interested in working on?

Yes

mauricionr commented 7 years ago

+1

patrick-steele-idem commented 7 years ago

In general, it is dangerous to start monkeying around with complex objects provided by the user since it can lead to a lot of corner case issues and performance problems. I'm not going to rule it out entirely and in the future we may be able to support this more fully. Right now, a shallow watch is implemented in a very efficient way. I'll keep the issue open for further discussion, but it's not something we will be able to support with the initial v4 release.

patrick-steele-idem commented 7 years ago

Actually, this is in the wrong repo :)