4

I have a button that is set to be disabled if a computed property's valid property is false. If true, the button should be enabled and allow a user to move to the next step in the current flow.

My currentStep computed property is updating perfectly on changes to the current step's inputs, but the button :disabled="currentStep.valid" isn't recognizing the changes that ARE HAPPENING to currentStep.valid.

If I click on the current component (addnewprogram) in vue-devtools to see it's data, the button displays correctly!

Seen here: http://recordit.co/XH6HX7JLhV

However, without clicking on addnewprogram in the devtools, it doesn't function correctly.

Is there an obvservation caveat I'm missing?

The code for this functionality can be found here:

<template>
  <section class="newprogram">

      <div class="newprogram--content">

        <div class="newprogram--stepone" v-if="progression.current === 1">
          <div class="content--left">
            <a class="link uppercase">use existing program information<i class="fa fa-picture-o"></i></a>
            <base-input v-for="input in currentStep.inputs"
                        :key="input.id"
                        :data="input"
                        v-model="input.value"></base-input>
          </div>
          <div class="content--right">
            <!-- images -->
          </div>
        </div>

        <div class="newprogram--steptwo" v-if="progression.current === 2">
          <choice-progression :step="1"></choice-progression>
        </div>

      </div>
    </div>

    <!-- Consistent among all steps -->
    <div class="container--bottomnav">
      <div class="bottomnav--left">
        <base-btn class="button-fluid"
                  :data="currentStep.btns[0]"></base-btn>
      </div>
      <div class="bottomnav--right">
        <base-btn :data="currentStep.btns[1]"
                  :disabled="currentStepValid"></base-btn>
      </div>
    </div>
    <!-- -->

  </section>
</template>

<script>
import bottomNav from '../main/bottom-nav.vue';
import baseProgressionBarbell from '../base/base-progression-barbell.vue';
import baseInstruction from '../base/base-instruction.vue';
import baseInput from '../base/base-input.vue';
import baseBtn from '../base/base-btn.vue';
import choiceProgression from '../secondary-flows/choice-progression.vue';

export default {
  name: 'addNewProgram',
  components: {
    bottomNav,
    baseProgressionBarbell,
    baseInstruction,
    baseInput,
    baseBtn,
    choiceProgression
  },
  computed: {
    progression () {
      return this.$store.getters.getProgression('addnewprogram');
    },
    steps () {
      return this.$store.getters.getSteps('addnewprogram');
    },
    currentStep () {
      return this.steps[this.progression.current - 1];
    },
    currentStepValid () {
      return this.currentStep.valid == false ? true : false;
    },
    stepOneValidation () {
      this.steps[0].inputs.forEach(input => {
        if (!input.value) {
          return this.$set(this.steps[0], 'valid', false);
        }
        this.$set(this.steps[0], 'valid', true);
      });
    },
    stepTwoChoices() {
      return this.$store.getters.getChoices('addnewprogram', 1);
    }
  }
}
</script>

<style lang="sass" scoped>
@import '../../sass/_variables.sass'

.newprogram
  display: flex
  flex-direction: column

.container--newprogram
  display: flex
  flex-direction: column
  height: 100%
  padding: $s1

.newprogram--header
  display: flex
  justify-content: space-between
  align-items: center

  h1
    padding: 0

.newprogram--content
  display: flex
  // justify-content: center
  // align-items: center
  height: 100%
  padding-top: $s2
</style>
yuriy636
  • 11,171
  • 5
  • 37
  • 42
Chris Johnson
  • 425
  • 1
  • 8
  • 19
  • Please use StackOverflow's code snippets to place code directly into your question. Links can break, causing the code to be lost from the question and losing valuable context to the problem you're experiencing. – B. Fleming Jan 03 '18 at 18:40
  • Since your project has a lot of code and a number of files, however, try to isolate the problem as much as possible, only include the relevant code snippets, and perhaps consider collapsing all but the `add-new-program.vue` file by default. – B. Fleming Jan 03 '18 at 18:46
  • @B.Fleming Fixed – Chris Johnson Jan 03 '18 at 18:57
  • Could you create a working snippet/fiddle of the issue? I tried to, by using your code, but there is too much data to mock. – yuriy636 Jan 03 '18 at 19:38
  • @yuriy636 That is why I didn't create a fiddle – Chris Johnson Jan 03 '18 at 20:45

1 Answers1

8

You are updating members of a computed item. Computed items aren't editable. You need a data item, or you need to write your changes to the $store and have them refresh from there.

Roy J
  • 42,522
  • 10
  • 78
  • 102
  • 1
    I tested this. This is the correct answer. You just got me over a two day hump, thank you. – Chris Johnson Jan 03 '18 at 20:22
  • I'm now using a data item for steps and changing the .valid property of the data item within stepOneValidation, which then triggers currentStep to re-evaluate, but it still isn't rendering my button as enabled unless I click on the component in the devtools – Chris Johnson Jan 03 '18 at 21:08
  • 1
    You've defined `stepOneValidation` as a computed, but it doesn't return anything. You're using it as a sort of multi-watcher? Also, it only looks at `steps[0]`; shouldn't it look at `currentStep`? – Roy J Jan 03 '18 at 21:36
  • So, if I call a mutation that sets the currentStep's valid property in my store, will that be reactive on currentStep? – Chris Johnson Jan 03 '18 at 21:53
  • 1
    If `this.steps` is a data item, no. If `steps` is a constantly refreshed pull of what's in `$store`, yes. – Roy J Jan 03 '18 at 22:00
  • @RoyJ - I just referred to this answer in another question here https://stackoverflow.com/questions/54715544/why-is-this-vue-computed-property-not-reactive. Would you mind taking a look? Thanks? – goodson Feb 15 '19 at 19:00