Vue string concatenation with values and conditional - vuejs2

Is there an option to display or hide a string based on a truthy value and when falsy it displays none, or can we only use ternary operator for this.
I know it is possible to do with class binding, where you add a value and then add the condition:
:class="{ 'class-only-if-true': false }"
so my question would be if it is possible to do the following only as a string:
{{'only display if true' : true}}
and possibly concatenate with data as such:
{{'only '+data+' if true' : true}}
While I know it would be possible adding a wrapper tag around this and adding the condition in here, but in this case I can't use any <div>, <span> or other.
While I could make it work as such (ternary operator):
{{ true ? 'only '+data+' if true' : ''}}
I was wondering if there would be an approach I have overlooked similar to the class binding condition.
Hope this makes sense.

Instead of the ternary operator {{ true ? 'only '+data+' if true' : ''}}, you could use the && operator like {{ true && 'only '+data+' if true'}}. Of course don't use data as it points to the components whole data object.

Related

how to use true and false statement in a binded class using vuejs

I have multiple errors if a user inputs the wrong details. I'm trying to change the border color to red if the error returns true and no border color if it returns false.
This is my code-
<Datepicker
:class="{
'form-error-outline':v$.allActivityPeriods.$each.$response.$errors[
index
].from.length > 0
}"/>
how do I add true or false statements to my bonded class?
Classes are conditionally added if the expression on the right-hand side evaluates to true. So if v$.allActivityPeriods.$each.$response.$errors[index].from.length > 0 equals true then the form-error-outline class will be applied to the element.
It looks like some deeply nested state, and I don’t know what that root v$ variable is. But you should have some sort of property (computed or otherwise) in your component itself that you can access and check:
<DatePicker
:class="{ 'form-error-outline': hasErrors['field_name'] }"
/>
export default {
computed() {
hasErrors(field) {
return field in this.errors && this.errors[field].length > 0;
},
},
};
You could do the following with an array syntax for the class and using ternary operators to check for conditions
<Datepicker
:class=“[v$.allActivityPeriods.$each.$response.$errors[index].from.length > 0 ?
'form-error-outline':
'regular style',
'more unconditional styles here'
]”

vue-select is showing ID instead of option value

I am using this https://vue-select.org/guide/values.html#caveats-with-reduce library for my application dropdown option.
<v-select
v-model="project_data.country"
label="text"
:options="project_data.countries"
:state="errors.length > 0 ? false : null"
:reduce="text => text.value"
/>
Now, on my local I can see the option value like this :
But on the server I can see the ID instead of the option value:
I do not understand why it's happening :(
Basically I am trying to use the :reduce props to get the single value as it's defined in the doc: https://vue-select.org/guide/values.html#transforming-selections

vue does not recover from me specifying a non existing location for v-model

When I have a textarea like
<textarea v-model="foo.abc.text"></textarea>
and either foo or foo.abc does not exist yet then
vue removes either parts of the DOM or is giving me a blank page.
It does never recover.
That alone is annoying, regardless of if I am using a debug version of vue or not.
If I try to use an approach that I have been advised to use earlier like
<textarea v-model="foo?.abc?.text"></textarea>
then I am still out of luck, I presume that I get a "rvalue" using those question marks and what I need rather is a variable location.
How do I, with as little trickery as possible, allow v-model to exist later on even if it doesnt exist now (late binding)?
Just shape your data accordingly and initialize it with empty values:
data(){
return {
foo: {
abc: {
text: ''
}
}
}
}
You can later populate it e.g. with the result of api call, but it's still better to initialize data properly
I would suggest going the :value + #input way. It allow more control over the input model, and does not require hiding it.
<textarea :value="!!foo && foo.abc.text" #input="(val) => !!foo && (foo.abc.text = val)" />
You can even hook in a validator:
<textarea
:value="!!foo && foo.abc.text"
#input="(val) => !!foo && (foo.abc.text = val)"
:rules="v => !v && 'The object has not been initialised'"
/>
I found a solution I can live with and then I got a comment in the same direction:
Conditionally showing the textarea.
v-if seems to do it but it falls under the "trickery" category, I think (angularjs would be more relaxed).
<textarea v-if="foo!=null" v-model="foo.abc"></textarea>
The symptom to hiding components if something is not all correct is not the best part of vue.js. Better show them and color them red.

Nuxt.js: Can I add a class using a ternary operator based on a Boolean from a prop?

I'm trying to use a Boolean in a prop to add a class based on a ternary operator. I'm obviously not doing it right because it is always evaluating to false.
<div :class="$style.inner + ' ' + (isRight == true ? 'is-right' : 'is-false')" :style="`color: #` + fontColor"></div>
If it's true, I need is-right added to the class, otherwise, this doesn't need to be added.
props: {
isRight: {
type: Boolean,
default: false
},
}
index.vue
<Signpost isRight=true/>
.is-right { padding-left:20% }
Looking at their Docs, I'm not sure I can do this with a Boolean actually.
To pass a Boolean to a prop you need to use v-bind or : like this:
<signpost v-bind:isRight="true" />
or
<signpost :isRight="true" />
Also if the only possible values for isRight is true or false you can shorten your ternary to just be:
:class="isRight ? 'is-right' : 'is-false'
I actually had a little syntax error for my prop that needed binding:
<Signpost :is-right="true"/>
And then on the div as #kissu said:
<div :class="[isRight ? 'is-right' : '']"></div>
Try passing the prop as :is-right="false" to have it passed down as Boolean and not as a basic String (is-right="false").
For the class, it can be written like as shown in the docs
<div :class="[isRight ? 'is-right' : 'is-false']"></div>
That way, you will even be able to do a strong equality check: isRight === true (comparing boolean to boolean).
VueJS devtools can help you see the type (thanks to the color).
There are some strongly recommended prop name casing recommendation that can be found here: https://v2.vuejs.org/v2/style-guide/#Prop-name-casing-strongly-recommended
props: {
greetingText: String // camel-cased here
}
<WelcomeMessage greeting-text="hi"/> <!-- kebab-cased here -->
Also, feel free to write ES6 template litterals, it may help the lecture. A working solution would be:
<div :style="`color: #${fontColor}`"></div>
Can also be done for your class, but I didn't want to risk a bad interpolation here.

SyntaxError: Unexpected token } in Vue js

My code is like this :
<multiple-photo-product :product="{{ isset($product) ? $product : '' }}"></multiple-photo-product>
When the code runs it throws an error:
SyntaxError: Unexpected token } in
But if the code is like this:
<multiple-photo-product product="{{ isset($product) ? $product : '' }}"></multiple-photo-product>
It doesn't throw an error.
I add :, so that the data is sent as an object.
If it does not use :, the data is sent as a string.
How can I solve it?
The problem lies in the fact that if the php variable $product is not set (i.e equals to null or ""), then Vue will try to bind the prop :product with '' which ultimately results to an error (like trying to make a :product="" bind)
Try the following:
<multiple-photo-product :product="{{ isset($product) ? $product : '""' }}"></multiple-photo-product>
Notice the double quotes "" surrounded by the single quotes. This will say to Vue to bind the product prop with an empty string, in case php's $product variable is not set.
Please also have a look here. You may find it helpful. The key point to recall is that v-bind expects valid javascript expressions, that is the interpolated value (i.e. whatever is inside the Blade's curly braces {{}}) must be a valid javascript expression too
In VueJS2, the attribute properties with : don't need the {{ }}. In your case, the ternary is like that :
<multiple-photo-product product="isset($product) ? $product : ''"></multiple-photo-product>
Source : https://v2.vuejs.org/v2/guide/syntax.html#Attributes
Mustaches cannot be used inside HTML attributes, instead use a v-bind directive