1

I am new to VueJS and after reading this doc section and this question, I can't figure how to change dynamically the prop active|positive|intermediary|negative and pulse of the following component (it could be another): vue-status-indicator

eg: with user.status = positive and the following wrong code :

<span v-for="user in users" :key="user.id">
  <status-indicator {{ user.status }}></status-indicator>
</span> 

What is the correct syntax to set theses type of props ?

1

1 Answer 1

1

You could do something like this.. I had to write a wrapper for it to make it functional..

[CodePen Mirror]

Edit To be clear - you cannot interpolate inside an attribute.. This has to do with boolean attributes in Vue..

This:

<status-indicator active pulse />

...is the same exact thing as doing this:

<status-indicator :active="true" :pulse="true" />

The "wrapper" component I wrote allows you to supply a string to set the status (like you are wanting to do):

<v-indicator status="active" pulse></v-indicator>
<!-- OR -->
<v-indicator status="positive" pulse></v-indicator>
<!-- OR -->
<v-indicator status="intermediary" pulse></v-indicator>
<!-- OR -->
<v-indicator status="negative" pulse></v-indicator>

Here is the full "wrapper" component, in .vue format: (added a validator for the 'status' prop)

<template>
  <status-indicator 
    :active="indicatorStatus.active" 
    :positive="indicatorStatus.positive"
    :intermediary="indicatorStatus.intermediary"
    :negative="indicatorStatus.negative"
    :pulse="pulse"
  ></status-indicator>
</template>

<script>
export default {
props: {
    status: {
      type: String,
      required: true,
      validator: (prop) => [
        'active',
        'positive',
        'intermediary',
        'negative',
      ].includes(prop)      
    },    
    pulse: {
      type: Boolean,
      required: false,
      default: false,
    },
  },
  data() {
    return { 
      indicatorStatus: {
        active: false,
        positive: false,
        intermediary: false,
        negative: false,
      }
    }
  },
  watch: {
    status() {
      this.handleStatusChange(this.status);
    }
  },
  methods: {
    handleStatusChange(newStatus) {
      Object.keys(this.indicatorStatus).forEach(v => this.indicatorStatus[v] = false);
      this.indicatorStatus[newStatus] = true;
    }
  },
  mounted() {
    this.handleStatusChange(this.status);    
  }    
}
</script>

Snippet:

const vIndicator = {
  template: "#v-indicator",
  props: {
    status: {
      type: String,
      required: true,
      validator: (prop) => [
        'active',
        'positive',
        'intermediary',
        'negative',
      ].includes(prop)      
    },    
    pulse: {
      type: Boolean,
      required: false,
    },
  },
  data() {
    return { 
      indicatorStatus: {
        active: false,
        positive: false,
        intermediary: false,
        negative: false,
      }
    }
  },
  watch: {
    status() {
      this.handleStatusChange(this.status);
    }
  },
  methods: {
    handleStatusChange(newStatus) {
      Object.keys(this.indicatorStatus).forEach(v => this.indicatorStatus[v] = false);
      this.indicatorStatus[newStatus] = true;
    }
  },
  mounted() {
    this.handleStatusChange(this.status);    
  }
}

new Vue({
	el: '#app',
  components: {
    vIndicator
  },
  data: {
    currentStatus: '',
    isPulse: '',
  }, 
  computed: {
    currentJson() {
      let cj = {
        currentStatus: this.currentStatus,
        isPulse: this.isPulse,
      };
      return JSON.stringify(cj, null, 2);
    }
  },
  mounted() {
    let statuses = ["active", "positive", "intermediary","negative"];
    let c = 0;
    let t = 0;
    this.currentStatus = statuses[c];
    this.isPulse = true;
    setInterval(() => {  
      t = c + 1 > 3 ? t + 1 : t;
      c = c + 1 > 3 ? 0 : c + 1;
      this.currentStatus = statuses[c];
      this.isPulse = (t % 2 == 0) ? true : false;
    }, 2000)
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://unpkg.com/vue-status-indicator@latest/dist/vue-status-indicator.min.js"></script>
<link href="https://unpkg.com/vue-status-indicator@latest/styles.css" rel="stylesheet"/>

<div id="app">
  <p>Will alternate status as well as pulsing (pulse changes after each full loop)</p>
  <!-- 
    [status]active|positive|intermediary|negative 
    [pulse]true|false
  -->
  <v-indicator :status="currentStatus" :pulse="isPulse"></v-indicator>
  <pre>{{ currentJson }}</pre>
</div>

<!-- WRAPPER COMPONENT -->
<script type="text/x-template" id="v-indicator">
  <status-indicator 
    :active="indicatorStatus.active" 
    :positive="indicatorStatus.positive"
    :intermediary="indicatorStatus.intermediary"
    :negative="indicatorStatus.negative"
    :pulse="pulse"
  ></status-indicator>
</script>

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

2 Comments

Thanks you very much. And for my knowledge, without writing a wrapper, it's not possible to change the props ?
Fully understood - thanks for the explanation and the example @Matt

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.