SyntaxError: Unexpected token } in Vue js - 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

Related

Cant load content – TypeError: Cannot read properties of null (reading 'attributes‘)

currently working on an issue and cant figure out why my page throws me an error.
Having this component:
<JobDetailSectionText
:variant="tmpl({ red: 1, blue: 4, yellow: 7 })"
:image-src="
jobProfile.attributes.imagePractice
? $strapi.options.url +
jobProfile.attributes.imagePractice.data.attributes.url
: '/static/img/praxisteil.jpg'
"
:image-alt="
jobProfile.attributes.imagePractice.data.attributes.alternativeText
"
>
In my content manager in Strapi I changed the „attribute.imagePractice" from required = true to false and now want to, if no file is added to the database show a default image in '/static/img/praxis.jpg‘.
But the console of the page gives me an error
"TypeError: Cannot read properties of null (reading 'attributes')
I tried to figure out the source of the problem but the page only works if I add and imagePractice in the backend, it won’t take the default img I tried to declare with the static path.
Any thoughts?
Thanks!
You can use optional chaining to check if property is exist
<JobDetailSectionText
...
jobProfile.attributes?.imagePractice
? $strapi.options.url +
jobProfile.attributes.imagePractice.data.attributes.url
: '/static/img/praxisteil.jpg'
"
...
>
#DinhTX solution is good, but note, that you cannot use optional chaining unless it's Vue 3. Read more here.
If you're using Vue version less then 3 you would need to write a computed property for that src attribute value where you'd check if attributes exist. Actually, I'd recommend you to use computed property anyway cause Vue's templates should be more HTML and less JS (not like React).
Example of computed property would be:
computed: {
jobSrc() {
const strapiUrl = `${$strapi.options.url}${jobProfile.attributes.imagePractice.data.attributes.url}`
return jobProfile.attributes?.imagePractice ? strapiUrl :'/static/img/praxisteil.jpg'
}
}

Can I pass a computed property and an object inside a v-bind:class in Vuejs?

I want to understand if I can do something like this, because I am trying but only getting erros... Forgive my bad english.
HTML file would be something like
<p :class="{mycss: isActive}, myComputedProperty" > My text </p>
and the component file would have something like
export default {
data () {
return {
isActive: true
}
},
computed: {
myComputedProperty () {
// do something
}
}
}
class value is an expression. If it doesn't make sense in raw JavaScript, it doesn't make sense there. Here comma operator is used, so the expression evaluates to myComputedProperty, and {mycss: isActive} part is discarded.
The format for combined class value is documented:
:class="[{mycss: isActive}, myComputedProperty]"
Since computed values are involved, defining the whole class object as a computed will result in cleaner template code.
I think the error is in your HTML - the comma is probably the cause. There are lots of ways to format strings, but this is one option:
<p :class="isActive ? 'mycss ' + myComputedProperty : myComputedProperty" > My text </p>

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.

Cypress Get Attribute value and store in Variable

I want to get the Attribute value and store in a variable how we can achieve this in cypress
In my case I want to get the complete class value and store it in variable.
This code just give me the attribute class value but how I can store the fetch value in variable
cy.get('div[class*="ui-growl-item-container ui-state-highlight ui-corner-all ui-shadow ui-growl-message"]').invoke('attr', 'class')
I was trying to compare the style of one element with another to make sure they were equal. Here's the code that seems to work for me.
cy.get('.searchable-group-selector-card-image')
.eq(4)
.invoke('attr', 'style')
.then(($style1) => {
const style1 = $style1
})
A good way to solve this kind of scenario is to use the alias mechanism. One could leverage this functionality to enqueue multiple elements and then check all of them together by chaining the results. I've recently come to a case in an SPA where the assertion had to happen between elements that were spread across different angular routes (call them different pages).
In your use case, this would like:
cy.get('.searchable-group-selector-card-image')
.eq(4)
.invoke('attr', 'style')
.as('style_1')
cy.get('.another-element')
.invoke('attr', 'style')
.as('style_2')
// later on for example you could do
cy.get('#style_1').then(style_1 => {
cy.get('#style_2').then(style_2 => {
// Both values are available and any kind of assertion can be performed
expect(style_1).to.include(style_2)
});
});
This is described in Variables and Aliases section of the Cypress Documentation.
Here is how I got the value of for attribute in a label tag which had text "Eat" inside.
cy.contains('Eat').then(($label) => {
const id = $label.attr('for');
}
Most important thing is to get the selector right, so it exactly finds the value you are looking for. In this case you already found it. By using then() gives you the ability to store it in a variable.
cy.get('div[class*="ui-growl-item-container ui-state-highlight ui-corner-all ui-shadow ui-growl-message"]').invoke('attr', 'class')
.then($growl-message => {
const message = $growl-message.text()
//do the checks with the variable message. For example:
cy.contains(message)
})
Note that the scope of the variable is within the curly brackets. Thus using the variable has to be within those curly brackets.

Vue string concatenation with values and conditional

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.