1

I'm looping through elements and I'm positioning div using top and left CSS properties:

<div
v-for="coord in coords"
:style="{ top: coord.y + 'px', left: coord.x + 'px' }"
></div>

Sometimes instead of top property I need to use bottom (this depends on one of my Vuex store values). How can I dynamically define if I should use top or bottom CSS property?

I tried to used computed prop isTopOrBottom which would return 'top' or 'bottom: :style="{ isTopOrBottom: coord.y + 'px', left: coord.x + 'px' }". But this is not working in Vue.

1
  • You could just create a component <coord> and then define a computed() property for the style. In the computed property, you can return an object depending on your conditions. Or - if you don't want to create a separate components - you could define a method and call it from the template. Then, pass the coords and return an object based on your conditions. Method calls are not cached like computed properties. Commented Nov 23, 2019 at 14:05

4 Answers 4

4

You can use the ternary operator (in case computed properties are not working) For example:

<span
class="description"
:class="darkMode ? 'dark-theme' : 'light-theme'"

>

Hope this help.

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

1 Comment

This is the correct answer. Ternary operator with computed property did the job: ` :style="{ top: isTop ? coord.y + 'px' : '', bottom: !isTop ? coord.y + 'px' : '', left: coord.x + 'px' }"`. Thank you!
3

It should be like JavaScript string concatenation

<div
v-for="coord in coords"
:style="'top: '+coord.y + 'px;left: '+coord.x + 'px'"
></div>

Vue.config.productionTip = false;
Vue.config.devtools=false;

var app = new Vue({
  el: '#app',
  data:{
    coords:[{y:10,x:10},{y:20,x:20},{y:30,x:30}]
  }
});
.border-line{
  border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<div id="app">
<div class="border-line"
    v-for="coord in coords"
    :style="'margin-top: '+coord.y + 'px;margin-left: '+coord.x + 'px'"
    >Test</div>
 </div>

Comments

0

You could do something like this:

:class="{ is-top: isTop, is-bottom: isBottom }"

And in your script:

computed() {
    isTop() {
        // return top condition
    },
    isBottom() {
        // return bottom condition
    }
}

Handle css:

.is-top {
    ...
}
.is-bottom {
    ...
}

1 Comment

I can't define .is-top and .is-bottom classes because their values are dynamically. So it needs to be inlined.
0

You can also use a Vuejs custom directive for this! https://v2.vuejs.org/v2/guide/custom-directive.html

Check this out:

In your template:

 <p v-position="expressionThatMakesItTop" v-if="isSignedIn">Welcome back {{user.email}}</p>

If you want to register a directive locally, components also accept a directives option, check that out on the documentation I linked. I am going to show you how to do it globally so in your main.js file, before constructing the Vue instance of course:

I left the console.log that displays the objects that you can use in your directive so you can explore them on your console and tailor this to your needs.

Vue.directive("position", {
  bind: function(el, binding, vnode) {
    console.log(el, binding, vnode);
    el.style.left = `${vnode.context.coord.x}px`;
    if (binding.value) {
      el.style.top = `${vnode.context.coord.y}px`;
      return;
    }
    el.style.bottom = `${vnode.context.coord.y}px`;
  }
});

Comments

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.