vendredi 8 mai 2015

Vue JS Watching deep nested object

Disclaimer: This is my first attempt at building an MVVM app I have also not worked with vue.js before, so it could well be that my issue is a result of a more fundamental problem.

In my view I have two types of blocks with checkboxes:

  • Type 1: block/checkboxes
  • Type 2: block/headers/checkboxes

The underlying object is structured like this:

{
  "someTopLevelSetting": "someValue",
  "blocks": [
    {
      "name": "someBlockName",
      "categryLevel": "false",
      "variables": [
        {
          "name": "someVarName",
          "value": "someVarValue",
          "selected": false,
          "disabled": false
        }
      ]
    },
    {
      "name": "someOtherBlockName",
      "categryLevel": "true",
      "variables": [
        {
          "name": "someVarName",
          "value": "someVarValue",
          "categories": [
            {
              "name": "SomeCatName",
              "value": "someCatValue",
              "selected": false,
              "disabled": false
            }
          ]
        }
      ]
    }
  ]
}

My objectives

Selecting checkboxes:

  1. User clicks on checkbox, checkbox is selected (selected=true)
  2. A method is fired to check if any other checkboxes need to be disabled (disabled=true). (If this method has indeed disabled anything, it also calls itself again, because other items could be in turn dependent on the disabled item)
  3. Another method updates some other things, like icons etc

Clearing checkboxes

A user can clicks on clear button, which unchecks (selected=false) all checkboxes in a list. This action should also trigger the methods that optionally disables checkboxes and updates icons etc.

My current method (which doesn't seem quite right)

  • The selected attribute of the data-model is bound to the checked state of the checkbox element via the v-model directive.
  • The disabled attribute (from the model) is bound to the element's class and disabled attribute. This state is set by the aforementioned method.
  • To initialize the methods that disable checkboxes and change some icons, I am using a v-on="change: checkboxChange(this)" directive. I think I need to do this part differently
  • The clearList method is called via v-on="click: clearList(this)"

The problems with my current setup is that the change event is not firing when the checkboxes are cleared programatically (i.e. not by user interaction).

What I would like instead
To me the most logical thing to do would be to use this.$watch and keep track of changes in the model, instead of listening for DOM events.

Once there is a change I would then need to identify which exact item changed, and act on that. I have tried to create a $watch function that observes the blocks array. This seems to pick up on the changes fine, but it is returning the full object, as opposed to the individual attribute that has changed. Also this object lacks some convenient helper attributes, like $parent.

I can think of quite a few hacky ways to make this work, but my use case seems pretty standard, so I expect there should be a much more elegant way to handle this.

Aucun commentaire:

Enregistrer un commentaire