Binding style css in vuejs - vue.js

I get into a problem. Here's my code:
<md-table-cell
:style="arrDisplay[1][i1+3] > 0 ? {background: 'orange'}: ''"
colspan="3"
v-for="(m1, i1) in 2"
:key="i1"
>
<div
contenteditable
v-text="arrDisplay[1][i1+3] > 0 ? arrDisplay[1][i1+3] : ''"
#blur="onEdit(1, i1+3)"
></div>
<div class="del" v-if="arrDisplay[1][i1+3] > 0">
<md-icon>clear</md-icon>
</div>
</md-table-cell>
I want the table cell have orange background when it's value > 0 else white. It work perfectly fine after calculate arrayDisplay but not when I edit it:
onEdit(y, x) {
var src = event.target.innerText
this.arrDisplay[y][x] = parseInt(src)
},
But if I edit it by Vue DeveloperTools it works. I think if I'm right the reason maybe Vue does not recognize that I change arrDisplay but have no idea how to fix it. What should I do ?

You are trying to update an item using an index in an array.
As explained here this is not reactive. That's why you don't see the update.
Try this:
Vue.set(this.arrDisplay[y], x, parseInt(src))
Note: make sure that this.arraDisplay[y] is reactive. If it is not, then you need to use Vue.set when creating it also.

Related

vue-gettext translate text

I am applying translation in vue 2.x and I am using "vue-gettext" but I am having a problem in some cases eg:
<settings-group label="is a label" >
<settings-field label="is a label">
In those cases I can't find a way to translate the label, I was looking for info and there is nothing, but maybe someone here could solve it...
Things I tried:
<settings-field v-translate label="is a label">
Doesn't work
<settings-field label="{{<translate>is a label</translate>}}">
Throw an error: Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of , use <div :id="val".
thank you.
First option (preferred, since in vue3-gettext translate tag would be eventually removed):
<settings-group :label="$gettext('is a label')" />
Second option -- create slot label in settings-group component. Could be useful if you going to interpolate string based on some data from settings-group
# settings-group.vue
<div class="settings-group">
<span class="label">
<slot name="label" v-bind="{ count }" />
</span>
...
# pages/settings.vue
<settings-group>
<template v-slot:label="{ count }">
<translate
:translate-n="count"
:translate-plural="%{count} elements"
:translate-params="{ count }"
>
%{count} element
</translate>
</template>
</settings-group>

Vue Material Checkbox Checked

I have tried / guessed at every combination of v-bind/v-model/:checked/:value I can think of, but I can't get these damn checkboxes checked on load:
Using Vue Material / Vue3:
<div v-if="items.length">
<div
v-for="(value,key,index) in this.items"
:key="index"
:ref="'icon'+items[key].id">
<md-checkbox
:id="'TDS'+key"
v-model="items[key].complete"
true-value="1"
#change="doDo(items[key].id)"
class="md-primary m-0"
>
{{ items[key].item }} {{items[key].complete}}
</md-checkbox>
</div>
</div>
The bit I can't figure out is how to make the checkbox checked if items[key].complete=1 when data is loaded.
You are already inside the loop
v-model="value.complete"
Same goes for all other bindings.
And your data should not be accessed with this in your template
v-for="(value,key,index) in items"
This one should already work, if you receive your data properly, it may update itself due to reactivity. Maybe try v-model="!!items[key].complete" just to be sure that your value is coerced to a Boolean.

Vuejs adding conditional style fails

I wuld like to add the following style iwhich workss in html
<div style="text-decoration: line-through">
Now am trying this in vuejs2
<div :style="{'text-decoration: line-through':true}">
But the above doesnt work
Where am i going wrong?
Binding an object to the style attribute is done by providing key / value pairs.
I suspect what you want is
<div :style="{'text-decoration': condition ? 'line-through' : 'initial'}">

vuejs :src with a v-if condition

This code works but is there a way to consolidate these two conditions and outputs into one line of code?
<img v-if="pointshover" :src="pointshover" :key="pointshover" class="leaderimg">
<img v-if="!pointshover" :src="leaderPoints[0].playerimg" :key="pointshover" class="leaderimg">
Basically if 'pointshover' is null then it grabs the image src from leaderPoints[0].playerimg. If 'pointshover' is not null then it is the src.
Option 1
Then as you want to use only one line, going with the solution proposed by #choasia with a small change.
<img :src="pointshover ? pointshover : leaderPoints[0].playerimg" :key="pointshover" class="leaderimg">
You won't need the v-if as this image is shown always, and it will have the pointshover src only when it exists and the leaderPoints[0].playerimg when it doesn't.
Option 2
If you go with the two lines code you probably should use:
<img v-if="pointshover" :src="pointshover" :key="pointshover" class="leaderimg">
<img v-else :src="leaderPoints[0].playerimg" :key="pointshover" class="leaderimg">
It's clearer what you want to accomplish if you use an else.
Option 3
You could use a computed property to bind the src.
<img :src="myImageSource" :key="pointshover" class="leaderimg">
myImageSource(){
return this.pointshover ? this.pointshover : this.leaderPoints[0].playerimg;
}
You can use JavaScript expressions in :src.
<img v-if="pointshover" :src="pointshover ? pointshover : leaderPoints[0].playerimg" :key="pointshover" class="leaderimg">

Selecting specific element in vue 2 inside v-for loop

Please see the code
<div v-for="msg in leftMsg">
div v-if="msg.last_sender" #click.prevent="loadMsg(msg)">
<tr :class="['active',{ 'seens' : !msg.seen, 'selected':msg.isActive}]">
// some html
</tr>
</div>
</div>
loadMsg(obj){
obj.isActive = !obj.isActive;
}
The problem is, it is adding selected class properly but when I click another item it adds selected but doesn't remove the old one. How can I keep only the most recent clicked item selected?
Thank you.
Add a data property outside of the msg objects and use that to track the active message.
data(){
return {
activeMessage: null,
...
}
}
Then in your template, set the activeMessage.
<div v-for="msg in leftMsg">
<div v-if="msg.last_sender" #click.prevent="activeMessage = msg">
<tr :class="['active',{ 'seens' : !msg.seen, 'selected': msg === activeMessage}]">
// some html
</tr>
</div>
</div>
The key parts I changed here are #click.prevent="activeMessage = msg" and 'selected': msg === activeMessage. This will set activeMessage to the clicked message, and then the selected class will be applied to the activeMessage and will only apply to the activeMessage.
I would also note that it's strange that you have a tr element nested inside div. I assume it was just because of your example, but that's not technically valid HTML.
I have solved this issue using a for loop. I thought it may help some other.
In order to remove the all other previous active classes all you need to run a for loop and make them false and then assign active=true to the newest one.
Here is the code that may help
// make all other selected class false first
for(let i=0; i<this.leftMsg.length; i++){
this.leftMsg[i].isActive=false;
}
/*now making the newest one active*/
obj.isActive = true;