Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested models and reactivity #12

Open
riker09 opened this issue Jun 12, 2018 · 0 comments
Open

Nested models and reactivity #12

riker09 opened this issue Jun 12, 2018 · 0 comments

Comments

@riker09
Copy link

riker09 commented Jun 12, 2018

I'm not quite sure if this is an issue with vue-rawmodel or Vue.js. but it seems that the support for nested models is limited or broken. Please see this demo for reference: https://codepan.net/gist/a7fe8b888cf6b5e92c84350e9ed22fbc

Basically I have two reactive models, where one model is a child of the other.

class MyModel extends ReactiveModel {
    name: string;
    locked: boolean;
    settings: Settings;

    public constructor({parent, ...data} = {}) {
        super({parent});

        this.defineField('name', { type: 'String', defaultValue: '' });
        this.defineField('locked', { type: 'Boolean', defaultValue: false });
        this.defineField('settings', { type: Settings, defaultValue: function() { return new Settings(); } });
    }
}

class Settings extends ReactiveModel {
    dummy: boolean;

    public constructor({parent, ...data} = {}) {
        super({parent});

        this.defineField('dummy', { type: 'Boolean', defaultValue: true });
    }
}

I have a custom form component named form-toggle looking like this:

Vue.component('form-toggle', {
  props: {
    value: { type: Boolean },
    onValue: { type: Boolean, default: true },
    offValue: { type: Boolean, default: false }
  },
  template: `<div>
    	<div class="toggle" :class="{on: isOn}">
        <div class="val" :class="{active: !isOn}" @click="turnItOff">off</div>
        <div class="val" :class="{active: isOn}" @click="turnItOn">on</div>
        <div class="marker"></div>
    	</div>
    </div>`,
  computed: {
    isOn: function() { return this.value === this.onValue }
  },
  methods: {
    turnItOn: function() { this.$emit('input', this.onValue); },
    turnItOff: function() { this.$emit('input', this.offValue); }
  }
});

And now we put it all together:

new Vue({
  el: "#app",
  data: {
    hasChanges: false,
    myModel: new MyModel()
  },
  computed: {
    status: function() { return this.hasChanges ? 'changed' : 'vanilla' }
  },
  methods: {
    stateChanged: function() {
      this.hasChanges = this.myModel.isChanged();
    },
    reset: function() {
      this.myModel.$rollback();
      this.hasChanges = this.myModel.isChanged();
    }
  }
});
</script>

For conveniance here's the template:

<div id="app">
  <h2>Model status: {{ status }}</h2>
  <div>
    <label for="name">
      Name:
      <input id="name" v-model="myModel.Name" @input="stateChanged" />
    </label>
  </div>
  <div>
    <p>Locked: {{myModel.locked}}</p>
    <form-toggle v-model="myModel.locked" @input="stateChanged"></form-toggle>
  </div>
  <div>
    <p>settings.dummy: {{myModel.settings.dummy}}</p>
    <form-toggle v-model="myModel.settings.dummy" @input="stateChanged"></form-toggle>
  </div>
  <button @click="reset">Reset</button>
  
  <h2>
    Raw output:
  </h2>
  {{ myModel }}
</div>

When I change the value of a non-nested property I'm unable to change the value of a nested property until I either reset ($rollback) the model or change the values back to their original state.

It feels like I'm missing something very obvious, but I've been trying to figure this one out for quite some time now. Hopefully you can shine some light on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant