I am using Vuejs with vuetify components i have customize my website to have two languages with Internationalization (i18n).
the problem is i also want to change my font when i change to my second language bur don't know how to do that.
style
.font{
font-family: 'b nazanin';
/*i want to use this font after i change my language*/
}
<template>
<button v-for="entry in languages" :key="entry.title" #click="changeLocale(entry.language)"v-on:click="font">
<flag :iso="entry.flag" ></flag>
{{entry.title}}
</button>
<h1 v-bind:style="{font}">{{ $t('titleInHome') }}</h1>
</template>
can anyone please help me in this case thank you all
You can do it with style binding.
HTML Template:
<html>
<body>
<div id="app">
<h1 :style="styles">Apply font here</h1> <br>
<button v-for="entry in langs" #click="changeFont(entry.title)" :key="entry.title">
{{ entry.title }}
</button>
</div>
</body>
</html>
Script:
new Vue({
el:"#app",
data:{
styleObj:{
color :'blue',
border: '2px blue dotted',
backgroundColor:'gray',
fontFamily:'Time New Roman'
},
langs:[
{ title :'Vue.js'},
{ title:'React'},
{ title:'Angular'}
]
},
methods:{
changeFont(lang){
let fontFamily = null;
if(lang == "Vue.js"){
fontFamily = "Arial";
}
else if(lang == "React"){
fontFamily = "Verdana";
}
else{
fontFamily = "Calibri";
}
this.styleObj.fontFamily = fontFamily;
}
}
});
Complete Example
You can use a dynamic style or a dynamic class, these can depend on some variable inside your code. See here for example:
https://v2.vuejs.org/v2/guide/class-and-style.html#Object-Syntax-1
For example you could write two classes and then something like this:
:class="{'classOne': languageA: , 'classTwo': languageB}" //(languageA and B would be bools in this case)
Related
I have a pill shape that say's either Production or Development. I want the background color to be different depending on if it is production or development. I've done this before with option api, but I'm having trouble in composition api.
Computed Method:
const reportStatus = computed(function() {
if (dashboard.status === 'Production') {return 'status--production'}
return 'status--qa'
});
Styling:
.status--production {
background-color: blue;
color: white;
}
.status--qa {
background-color: green;
color: white;
}
Template code:
<div>
<span class="float-left text-center w-24 inline-block flex-shrink-0 rounded-full px-2 py-0.5 text-xs font-medium text-white inset-x-0 top-0" :class="reportStatus">
{{ dashboards.status }}</span>
</div>
Script Dashboard code:
const dashboard = [
{
report: "Ad Hoc",
description: "",
status: "Production"
},
Use computed properties for things like changing reactive variable output. For example, some different date format.
The best way to your issue is:
<template>
<span class="fload ..." :class="[ dashboard.status === 'Production' ? 'status-production' : 'status-qa']">{{ dashboard.status }}</span>
</template>
Make sure dashboard is a reactive object/value like ref() or reactive() second one fit best for objects. Objects are tricky to use every time you have to assign a full new object instead of just change a value in it.
Computed property:
<template>
<div>
<span class="float ..." :class="addClass">{{ dashboard.status }}</span>
<button #click="dashboard = { ...dashboard, status: 'lol' }">Change</button>
<button #click="dashboard = { ...dashboard, status: 'Production' }">Production</button>
</div>
</template>
<script setup>
const dashboard = ref({ status: 'Production' })
const addClass = computed(() => dashboard.value.status === 'Production' ? 'status-production' : 'status-qa')
</script>
If you use ref() and change dashboard like "dashboard.value.status = 'some value'" reactivity won't work same as "dashboard.status = 'some value'" in template. You will always need to assign a new object to trigger reactivity.
reactive() don't have that problem because all items inside of it are reactive.
When you have two class attributes, the second one gets ignored. Combine your two class attributes into one;
<div>
<span :class="`float-left text-center w-24 inline-block flex-shrink-0 rounded-full px-2 py-0.5 text-xs font-medium text-white inset-x-0 top-0 ${reportStatus}`">
{{ dashboards.status }}
</span>
</div>
Your code should work fine, Just for a demo purpose I am using just an object for dashbaords variable but you can change it to an array as per your requirement.
Here is the live demo (Please have a look and try to find the root cause of the issue you are facing by referring this) :
const { ref, computed, onMounted } = Vue;
let options = {
setup: function () {
let dashboards = ref({});
const reportStatus = computed(function() {
return (dashboards.value.status === 'Production') ? 'status--production' : 'status--qa'
});
onMounted(function() {
dashboards.value = {
report: "Ad Hoc",
description: "",
status: "Production"
}
});
return {
dashboards,
reportStatus
};
}
};
let appVue = Vue
.createApp(options)
.mount('#app');
.status--production {
background-color: blue;
color: white;
border: 1px solid black;
}
.status--qa {
background-color: green;
color: white;
border: 1px solid black;
}
<script src="https://unpkg.com/vue#3.0.0-beta.14/dist/vue.global.js"></script>
<div id="app">
<span :class="reportStatus">
{{ dashboards.status }}
</span>
</div>
I'm using the npm module if-emoji to detect whether a user can view emojis or not. There is a similar tool in Modernizr.
If the user can't view emojis, I'm displaying an image of the emoji instead. So my Vue HTML looks like this:
<h2 v-if="this.emojis">😄</h2>
<h2 v-if="!this.emojis"><img src="https://example.com/emoji.png">/h2>
Does this still download the image for users who can view emojis, therefore using bandwidth unecessarily?
And is there a more efficient way of doing this, so that I don't need to go and add v-if every time I use an emoji? Can there be some sort of lookup table, if there's an emoji and !this.emojis?
You can solve this also by creating your own vue.component
<emojiorimage usesmily="false" smily="😄" imgpath="https://i.stack.imgur.com/QdqVi.png"></emojiorimage>
that capsulates the decision if image or smily inside itself.
var app = new Vue({
el: "#app",
data: function(){
return {
extendedCost: 0,
}
},
components: { "emojiorimage" : {
template : `
<h2>
usesmily is {{usesmily}}<br/>
<div v-if="usesmily === 'true'">{{ smily }}</div>
<div v-else><img :scr="imgpath" width="50" height="50" :alt="imgpath" /></div>
</h2>`,
props: ["usesmily", "smily", "imgpath"],
}}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h1>Emoji or Image</h1>
<emojiorimage
usesmily="false"
smily="😄"
imgpath="https://i.stack.imgur.com/QdqVi.png"
></emojiorimage>
<emojiorimage
usesmily="true"
smily="😎"
imgpath="https://i.stack.imgur.com/QdqVi.png"
></emojiorimage>
</div>
You can then feed it the isemoji from your npm package that you query once and store somewhere.
For seperate vue files it would look kind of like this:
emojiorimage.vue
<template>
<h2>
<div v-if="usesmily === 'true'">{{ smily }}</div>
<div v-else><img :scr="imgpath" width="50" height="50"
:alt="imgpath" /></div>
</h2>
</template>
<script>
export default {
props: ["usesmily", "smily", "imgpath"],
};
</script>
App.vue
<template>
<div id="app">
<h1>Emoji or Image</h1>
<emojiorimage
usesmily="false"
smily="😄"
imgpath="https://i.stack.imgur.com/QdqVi.png"
/>
<emojiorimage
usesmily="true"
smily="😎"
imgpath="https://i.stack.imgur.com/QdqVi.png"
/>
</div>
</template>
<script>
import emojiorimage from "./components/emojiorimage.vue";
export default {
components: {
emojiorimage,
},
};
</script>
index.html
<div id="app"></div>
index.js
import Vue from "vue";
import App from "./App";
Vue.config.productionTip = false;
new Vue({
el: "#app",
template: "<App/>",
components: { App }
});
to get:
Learning resources:
https://v2.vuejs.org/v2/guide/components.html
https://v2.vuejs.org/v2/guide/single-file-components.html
This should work as well:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<h2 v-if="true">😄</h2>
<h2 v-else><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/1200px-SNice.svg.png" width=15 height=15></h2>
<h2 v-if="false">😄</h2>
<h2 v-else><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/1200px-SNice.svg.png" width=15 height=15></h2>
The v-if part only is part of the sourcecode if the statement is true - else the else statement is in instead. If the img tag is not part of the loaded source the image wont be loaded.
<h2 v-if="emojis">😄</h2>
<h2 v-else><img src="https://example.com/emoji.png"></h2>
Is probably the only way to improve your code as #Patrick Artner pointed out.
You do not need this. in the template
To the question if the image is loaded if it is not shown the simple answer is no. Vue only renders v-ifs when they are needed and does not render it - the image is loaded only if !emojis.
Thanks to #PatrickArtner who posted the idea of using a Vue component to render the emoji / image. Here is my final solution, which resizes the emoji / image to fit the surrounding text — it uses fitty to resize the emojis, and sets the images to height:1em;.
Emoji.vue
<template>
<div class="emojiContainer">
<span id="fittyEmoji" v-if="emojis">{{ insert }}</span>
<img v-if="!emojis" :src="insert" class="emojiImage">
</div>
</template>
<style scoped>
.emojiContainer {
display: inline;
}
.emojiImage {
height:1em;
}
</style>
<script src="fitty.min.js"></script>
<script>
import fitty from 'fitty';
import ifEmoji from 'if-emoji'
export default {
name: 'Emoji',
props: ['name'],
data: function() {
return {
insert: "",
emojis: false,
}
},
methods: {
insertEmoji(){
var names = ['frog', 'fire']
var emojis = ['🐸','🔥']
var urls = ['https://example.com/frog.png',
'https://example.com/fire.png']
if (this.emojis) {
this.insert = emojis[names.indexOf(this.name)];
} else {
this.insert = urls[names.indexOf(this.name)];
}
fitty('#fittyEmoji')
}
},
beforeMount() {
if (ifEmoji('🐸')) {
this.emojis = true;
} else {
this.emojis = false;
}
this.insertEmoji();
}
}
</script>
Then in your parent components you can just insert like this:
<template>
<div id="app">
<h1><Emoji name='frog'/> Frog Facts</h1>
<p>Lorem ipsum <Emoji name='fire'/><p>
</div>
</template>
<script>
import Emoji from '#/components/Emoji.vue'
export default {
components: {
Emoji,
},
};
</script>
I want to change font(text) color when user pick it from color picker,I had made this but it wont work,
<textarea :class="changeColor"></textarea>
<v-color-picker class="ma-2" hide-inputs #click="changeColor('color')"></v-color-picker>
changeColor(val){ this.color = val}
To dynamically assign a css color value to a html element you can use :style="{}" .
Like this
<template>
<div>
<textarea :style="{color:color}"></textarea>
<v-color-picker v-model="color" />
</div>
</template>
<script>
export default {
data() {
return {
color : '#FFFFFF'
}
}
}
</script>
Is it possible to dynamically change the content of a scoped inside a Single File Component?
You could do it using the v-html directive.
Since I don't know your actual code I will just give you the code for a basic proof of concept.
In the template...
<template>
<div>
<head v-html="styles"></head>
<div class="test">
<p>change this paragraph</p>
</div>
<textarea name="" id="" cols="30" rows="10" v-model="csscode"> </textarea>
</div>
</template>
In the script...
<script>
export default {
data() {
return{
csscode: null,
styles: null,
}
},
watch:{
csscode(val){
this.styles = '<style>' + val + '</style>';
}
}
}
</script>
Inside style tag, no. Its not possible because of build extracts a .css file.
But as an alternative you can use javascript object as an style object.
var app = new Vue({
el: '#app',
data: function(){
return {
textAreaStyle: {border: '2px solid blue', color: 'red', width: '500px', height: '300px'}
}
},
methods: {
updateStyle (event) {
this.$set(this.$data, 'textAreaStyle', JSON.parse(event.target.value));
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<textarea :style="textAreaStyle" #change="updateStyle">{{textAreaStyle}}</textarea>
</div>
I use VueJS 2 to render and calculate form items. Now I need to show a number if a propertie is under 10, and I need show a text message if the propertie is over or equal 10.
I use this code:
Vue.component('mycomponent', {
template: '#mytemp',
data: function() {
// ...
},
computed: {
mycomputedprop: function() {
if (this.model_a < 10) {
return '<span class="numbervalue">' + this.model_a + '€</span>';
} else {
return '<span class="textvalue">I\'ll contact you as soon as possible!</span>';
}
}
}
});
I use this code to show the value:
<div id="app">
{{ mycomputedprop }}
</div>
The problem is: if I show this value it shows the HTML code as text, not as HTML. How can I show the returned value as a HTML code?
You could use v-html
Document : Raw-HTML
<div id="app">
<div v-html="mycomputedprop"></div>
</div>
The contents of this div will be replaced with the value of the
rawHtml property, interpreted as plain HTML - data bindings are
ignored. Note that you cannot use v-html to compose template partials,
because Vue is not a string-based templating engine. Instead,
components are preferred as the fundamental unit for UI reuse and
composition.
Vue 3 Example:
const RenderHtmlApp = {
data() {
return {
rawHtml: '<span style="color: red">This should be red.</span>'
}
}
}
Vue.createApp(RenderHtmlApp).mount('#example1')
<script src="https://unpkg.com/vue#next"></script>
<div id="example1">
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
</div>
Assuming that modal_a is defined in the data of your component, why not handle this within the component template?
<div id="app">
<span v-if="model_a < 10" class="numbervalue">{{model_a}} €</span>
<span v-else class="textvalue">I\'ll contact you as soon as possible!</span>
</div>