1

I have seen a few questions similar to this but all revolve around webpack, which I am not currently using.

I have a Vue template:

    var question = Vue.component('question', {
    props: {
        scenario: { type: Object }
    },
    beforeMount: function () {
        this.retrieveScenario();
    },
    methods: {
        postChoice: function () {
            Post("Study", "PostScenarioChoice")
        },
        retrieveScenario: function () {
            Get("ScenariosVue", "GetScenario", 1, this,
                (c, data) => { this.scenario = data; },
                (c, errors) => { console.log(errors); }
            );
        }
    },

    template:
        `<div class="visible">
                <div class="row justify-content-center">
                    <div class="col-lg-6">
                        <a v-on:click="this.postChoice">
                            <img class="img-fluid" v-bind:src="scenario.scenarioLeftImg" />
                        </a>
                </div>
                <div class="col-lg-6">
                    <a v-on:click="this.postChoice">
                        <img class="img-fluid" v-bind:src="scenario.scenarioLeftImg" />
                    </a>
                </div>
            </div>
            </div >`

});

The Ajax retrieval returns an object with the following:

returned 
Object { 
    scenarioId: 1, 
    description: "Dog vs Bolard", 
    scenarioLeftImg: "images\\Scenarios\\bolard_dog_Left.png", 
    scenarioRightImg: "images\\Scenarios\\bolard_dog_Right.png",
    participantScenarios: [], 
    scenarioTypesScenarios: [] 
}

However, the Html, doesn't add the src tag to the tag and I'm really not sure why because the data's clearly available.

Much Help would be greatly appreciated.

3
  • 1
    You have backslashes in your src. Replace those by slashes. Commented Mar 21, 2018 at 13:49
  • Hi @connexo, done that but hasn't worked i'm afraid Commented Mar 21, 2018 at 13:51
  • Pick your answer. Commented Mar 24, 2018 at 18:30

2 Answers 2

1

This is happening because Vue's template system doesn't "watch" properties (or nested properties) of an object for changes. If you need to do this, then you can either use the computed property with a watch on the computed property, or you can just create two props instead of the single prop. Here is what I would do to change your code:

var question = Vue.component('question', {
  props: {
    // Replace this prop with the two below.
    // scenario: { type: Object }
    scenarioLeftImg: { type: String },
    scenarioRightImg: { type: String }
  },
  beforeMount: function () {
    this.retrieveScenario();
  },
  methods: {
    postChoice: function () {
      Post("Study", "PostScenarioChoice")
    },
    retrieveScenario: function () {
      Get("ScenariosVue", "GetScenario", 1, this,
        (c, data) => { this.scenario = data; },
        (c, errors) => { console.log(errors); }
      );
    }
  },
  template:
    `<div class="visible">
      <div class="row justify-content-center">
        <div class="col-lg-6">
          <a v-on:click="this.postChoice">
            <img class="img-fluid" v-bind:src="scenarioLeftImg" />
          </a>
        </div>
        <div class="col-lg-6">
          <a v-on:click="this.postChoice">
            <img class="img-fluid" v-bind:src="scenarioLeftImg" />
          </a>
        </div>
      </div>
    </div >`
});

Sign up to request clarification or add additional context in comments.

Comments

0

Your main issue is that due to the limitations of Javascript, Vue cannot detect property additions in Objects.

Change to

retrieveScenario: function () {
        Get("ScenariosVue", "GetScenario", 1, this,
            (c, data) => { Vue.set(this.data, 'scenarios', data); },
            (c, errors) => { console.log(errors); }
        );
    }

Please be aware that it is considered really bad practice to have components modify their props. Rather mirror those props into your vm's data() function in the created() hook of your component, then modify that. If you need the "modified" props outside of your component, emit an event telling those components props has changed.

Also replace the backslashes in your path by slashes:

scenarioLeftImg: "images\\Scenarios\\bolard_dog_Left.png", 
scenarioRightImg: "images\\Scenarios\\bolard_dog_Right.png",

has to be

scenarioLeftImg: "images/Scenarios/bolard_dog_Left.png", 
scenarioRightImg: "images/Scenarios/bolard_dog_Right.png",

5 Comments

This doesn't seem to have worked. If there is a different implementation you think suits better, please let me know. I am very new to Vue and also complex JS as a whole.
I'm afraid that to work with complex stuff needs you diving into the complexity - there's no way around that, but Vue.js makes this considerably less painful than e.g. Angular or React...
Hi @connexo i completely understand, just wondering if you think i'm going down the completely wrong path or if it is correct just needs tweaking and if so how?
First and foremost stop manipulating props inside components. Props should be considered read-only inside the component.
Do everything connexo says, then ask yourself "why am I modifying a property?" Components should not modify their properties. If your component looks after it's own state then your scenario object should be in the data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.