vue-i18n: component interpolation with html tags - vue.js

i'm using component interpolation as described here but also have some html tags in my translation string for formatting purposes. how should i deal with this?
<i18n
path="description"
tag="p"
:places="{ value1, value2, routerLink }"
/>
the corresponding key in my .yml file look like:
description: Lorem ipsum <nobr><strong>{value1} %</strong></nobr> some more text <nobr><strong>{value2} %</strong></nobr> and some more text. Go to {routerLink} for more info.

Try use v-html directive
<i18n
v-html="description"
tag="p"
:places="{ value1, value2, routerLink }"
/>
An alternative is can be use a computed that interprets HTML entities see this

Related

Vue slots with variable HTML passed in

I have a string that contains some HTML markup.
I would like to pass this into a component's slot.
This component is used elsewhere with regular html markup between the opening and closing tags, and works as expected.
The issues are that mustache syntax outputs escaped HTML, {{myFormattedText}} becomes literally Some line of <span>text with formatting</span> that is passed in from somewhere else which is not what we want.
Passing it in the v-html="myFormattedText" attribute on the component replaces all content inside the component tags with the variable string.
Is there a way to do this? I'd like to reuse this component, for visual consistency reasons, but the content that we receive for it is disparate and varies widely based on the view or source.
Test string:
myFormattedText = "Some line of <span>text with formatting</span> that is passed in from somewhere else";
Component:
<template>
<div class="doing-a-thing">
<h2>Some text</h2>
<div class="thing">Random stuff</div>
<slot></slot>
</div>
</template>
Attempts:
<mycomponent>{{myFormattedText}}</mycomponent>
<mycomponent v-html="myFormattedText"></mycomponent>
Just put the v-html render on an element inside the component tags and it'll get rendered correctly and passed in.
<mycomponent><div v-html="myFormattedText"></div></mycomponent>
Again, moments after posting, it hits me like a bolt of lightning...

Prevent vue render newline between elements

<template>
<div>
<span>foo</span> <!-- unwanted space here -->
<span>bar</span>
<span>foo</span>
</div>
</template>
// But I don't want to do this
<template>
<div>
<span>
foo
</span><span> <!-- bad coding style -->
bar
</span><span>
baz
</span>
</div>
</template>
In html, newlines between elements are rendered as spaces, and Vue followed that behavior. If I want no spaces between the elements, the obvious way is to put no space there, as shown in the code sample. But it is ugly, I don't want that. How can I do otherwise such that there is no space between the elements?
You can change the compiler options.
compilerOptions
type: Object
default: {}
Options for the template compiler. When using the default vue-template-compiler, you can use this option to add custom compiler directives, modules, or discard whitespaces between template tags with { preserveWhitespace: false }.
However the documentation states this only applies to single file components and template tags. I don't think there is currently any option for native tags and related issue has been closed. But maybe it gives you the desired result.

Vuejs, How can I resolve expressions within a string got as a prop?

I'm sorry if this is already solved but I'm not able to find it so I gonna try to be quick.
Imagine one of the props received by my component has the following value:
myAnnoyingProp: "Position of {{$data.name}} {{maritalStatus?\'married\':\'free\'}}"
I tried the following two options but I've got the same result for both:
<label v-html="element.label"></label>
<label>
{{element.label}}
</label>
Expected result:
Position of TheNameSetted free
Obtained result:
Position of {{$data.name}} {{maritalStatus?\'married\':\'free\'}}
PD: I'm using Vue 2.4.2
You could move the login inside your component by making use of 2 props, for example name, which is a String, and maritalStatus, which is either a String or Boolean depending on your needs (the example assumes a Boolean for maritalStatus). Then inside your component construct the message you want to display:
<label>
Position of {{element.name}} <span v-if="maritalStatus">Free</span><span v-else>Married</span>
</label>
You could also use string literals:
myAnnoyingProp: `Position of ${name} ${maritalStatus}`

How to interpolate a variable into a nested component in Vue?

I have an app that has components nested inside. The app is called on the filter id. I have a data element named minTotalSpent. Currently, this contains "3" in the app. The first placement on the page displays appropriately. When I try to pass it in as a variable into vue-slider, however, it does not like it and throws an "invalid expression"warning on the counsel and does not respect the minimum.
<div id="filter">
<form id="search">
Search <input name="query" v-model="searchQuery">
</form>
{{minTotalSpent}}
<div class="filter-container-slider">
<vue-slider
:min="{{minTotalSpent}}"
:max="42"
:value="2"
>
Just elaborating as per #thanksd's answer.
When using any component, over here vue-slider component, if you use v-min = "..." or :min = "...", the value of v-min or :min is in a javascript expression and you cannot use mustaches inside javascript expression.
And when it comes to html attributes like id on any element, you should be using v-bind.
<div v-bind:id="dynamicId"></div>
Read more about them here: https://v2.vuejs.org/v2/guide/syntax.html#Attributes

How to get the base asset url in a Shopify liquid theme?

is there a way to get the base asset url in a Shopify liquid theme?
I'm translating a page to Shopify. This page uses Vuejs data binding like so:
<img src="/path/to/assets/folder/{{ color }}1.jpg">
I can't pass the curly braces to the filter because it will URL encode it. If I had access to the asset url it would be simple.
Any ideas?
You can escape liquid templates, so your tag would be like this
<img src="/path/to/assets/folder/{{ "{{ color " }}}}1.jpg">
not nice if you ask me. But there is another option, use vue bind instead of text interpolation, so there is no curly braces, when you use the v-bind directive, then you write pure javascript for that directive, so you quote your src attribute, or add it to a variable of your component.
usign the text
<img :src=" '/path/to/assets/folder/' + color + '1.jpg' ">
usign a variable
<!-- template -->
<img :src="img_path">
// js, data or props attribute
img_path: '/path/to/assets/folder/' + color + '1.jpg'
note: I used the shorthand version of v-bind:src => :src