UncountedBrute
UncountedBrute

Reputation: 506

Having issues with getting VueJS to accept dynamic image string

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.

Upvotes: 1

Views: 417

Answers (2)

connexo
connexo

Reputation: 56823

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",

Upvotes: 0

th3n3wguy
th3n3wguy

Reputation: 3747

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 >`
});

Upvotes: 1

Related Questions