Render the binding value in dynamic generated html template in vuejs2 - javascript

For following code: I want the "test1 span" could be changed with javascript. How can I do it? NOTE: the {{msg}} maybe from ajax output.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<!-- app -->
<div id="app">
<span v-html="test"></span>
<span v-html="test1"></span>
{{test3}}
</div>
<script>
var app1 = new Vue({
el: '#app',
data: {
test: '<p style="color: red">THIS IS HTML</p>',
test1: '{{msg}}',
test3: 20,
msg: 10
}
})
function change() {
app1.msg = Math.random()
app1.test3 = Math.random()
}
setInterval(change, 2000)
</script>
</body>
</html>
Modification:
Maybe I need to make my question clear:
For next modify code, when launch the page, you will see Go to Foo link in the page, then you click the link, you will see hello {{msg}}
NOTE: this comes from the remote server: b.html.
I set a timer there, every 2 seconds, change the value of msg, I wish the {{msg}} in page could change to a random number.
main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/2.7.0/vue-router.min.js"></script>
</head>
<body>
<div id="app">
<p>
<router-link to="/foo">Go to Foo</router-link>
</p>
<router-view></router-view>
</div>
<script>
const Foo = {
template: '<div v-html="template1"></div>',
data: function () {
return {
template1: null
}
},
created: function () {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
fetchData () {
var that = this
$.get("http://localhost/try/b.html", function(data, status) {
that.template1 = data
})
}
}
}
const routes = [
{ path: '/foo', component: Foo }
]
const router = new VueRouter({
routes
})
const app = new Vue({
router
}).$mount('#app')
function change() {
app.msg = Math.random()
}
setInterval(change, 2000)
</script>
</body>
</html>
b.html
<div>
hello
{{msg}}
</div>

Use the tools that Vue.js gives you. Put change() in your VM's methods object, then create a created() hook that sets up the interval.
Please note that v-html expects a String, not a Number, so just add .toString() when generating the random number.
var app1 = new Vue({
el: '#app',
data: {
test: '<p style="color: red">THIS IS HTML</p>',
test1: null,
test3: 20,
msg: 10
},
watch: {
msg: function(newVal, oldVal) {
this.test1 = newVal
}
},
methods: {
change() {
this.msg = Math.random().toString()
this.test3 = Math.random()
}
},
created() {
setInterval(this.change, 2000)
}
})
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
<div id="app">
<span v-html="test"></span>
<span v-html="test1"></span>
{{ test3 }}
</div>
Instead of a watcher it is even easier to go for a computed property instead.
var app1 = new Vue({
el: '#app',
data: {
test: '<p style="color: red">THIS IS HTML</p>',
test3: 20,
msg: 10
},
computed: {
test1() {
return this.msg.toString()
}
},
methods: {
change() {
this.msg = Math.random()
this.test3 = Math.random()
}
},
created() {
setInterval(this.change, 2000)
}
})
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
<div id="app">
<span v-html="test"></span>
<span v-html="test1"></span>
{{ test3 }}
</div>

Use v-model instead of v-html :-
var app1 = new Vue({
el: '#app',
data: {
test: '<p style="color: red">THIS IS HTML</p>',
test1: '{{msg}}',
test3: 20,
msg: 10
}
})
function change() {
app1.msg = Math.random()
app1.test3 = Math.random()
}
setInterval(change, 2000)
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
<div id="app">
<span v-html="test"></span>
<span v-model="test1">{{msg}}</span>
{{test3}}
</div>

Finally I get the answer from here
Vue.compile( template )
this will make the template from remote server be parsed again by vuejs.
main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/2.7.0/vue-router.min.js"></script>
</head>
<body>
<div id="app">
<p>
<router-link to="/foo">Go to Foo</router-link>
</p>
<router-view></router-view>
</div>
<script>
const Foo = {
data: function () {
return {
template1: null,
msg: null
}
},
created: function () {
this.fetchData()
setInterval(this.change, 2000)
},
render: function(createElement) {
if (this.template1)
{
return this.template1();
}
},
methods: {
change() {
this.msg = Math.random()
},
fetchData () {
var that = this
$.get("http://localhost/try/b.html", function(data, status) {
that.template1 = Vue.compile(data).render
})
}
}
}
const routes = [
{ path: '/foo', component: Foo }
]
const router = new VueRouter({
routes
})
const app1 = new Vue({
router
}).$mount('#app')
</script>
</body>
</html>
b.html
<div>
hello
{{msg}}
</div>

Related

How to dynamically have label based on resource type for vue-multiselect

i have a requirement where autocomplete comes from backend and it will have key called filedId based on that i want to show the label
if we click on dynamic resource 1 btn the label should be city
if we click on dynamic resource 2 btn the label should be pinCode
if we click on dynamic resource 3 btn the label should be countryCode
Note: i don't want to change the data structure / json
here is what i have tried
var app = new Vue({
el: '#app',
components: { Multiselect: window.VueMultiselect.default },
data () {
return {
value: [],
options: [],
infoData:{},
}
},
methods:{
dr1(){
let infoObj = {
resource:{
autocomplete:{
fieldId:'city',
},
data:[{
id:1,
city:'Bengaluru'
}],
}
}
this.infoData = infoObj;
this.options = infoObj.resource.data;
},
dr2(){
let infoObj = {
resource:{
autocomplete:{
fieldId:'pinCode',
},
data:[{
id:1,
pinCode:'560097'
}],
}
}
this.infoData = infoObj;
this.options = infoObj.resource.data;
},
dr3(){
let infoObj = {
resource:{
autocomplete:{
fieldId:'countryCode',
},
data:[{
id:1,
countryCode:'+91'
}],
}
}
this.infoData = infoObj;
this.options = infoObj.resource.data;
},
determineLabel(){
let labelName = this.infoData.resource.autocomplete.fieldId;
return labelName;
}
},
})
body { font-family: 'Arial' }
<!DOCTYPE HTML>
<html>
<head>
<title>Timeline</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-multiselect#2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.1.0/dist/vue-multiselect.min.css">
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
</head>
<body>
<div id="app">
<button #click="dr1()">dynamic resource 1</button>
<button #click="dr2()">dynamic resource 2</button>
<button #click="dr3()">dynamic resource 3</button>
<br/><br/>
<div>
<multiselect
v-model="value"
label="determineLabel"
:options="options"
:multiple="false"
:taggable="false"
></multiselect>
</div>
</div>
</body>
here is codepen link to play with: https://codepen.io/eabangalore/pen/MWmrOBb
Still i did not find solution, please help me thanks in advance
Label prop in <multiselect> doesn't execute determineLabel by itself. it only gets computed or data option or a simple string. so you should put determineLabel in the computed:
...
computed: {
determineLabel() {
let labelName = this.infoData.resource.autocomplete.fieldId;
return labelName;
}
}
...

How to insert PHP variable to Vue computed functions in Laravel blade?

I need to bind $price_php with price in this Vue object. We do not use templates and imported components in the project
<html >
<head>
<meta charset="utf-8">
<title>Laravel</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="example">
<?php $price_php = 100 ?>
<p>Price: "{{ $price_php }}"</p>
<p v-bind:price="$price_php">Computed amount: "#{{ amount }}"</p>
</div>
<script>
var vm = new Vue({
el: '#example',
data: {
quantity: 10
},
// props: ['price'],
computed: {
amount: function () {
return price*this.quantity
}
}
})
</script>
I believe something like this would work for you.
<script>
var vm = new Vue({
el: '#example',
data: {
quantity: 10,
price: <?php echo $price_php; ?>,
},
// props: ['price'],
computed: {
amount: function () {
return this.price*this.quantity
}
}
})
</script>
Reference of Idea: See "Rendering JSON" subheading on https://laravel.com/docs/7.x/blade#displaying-data

MathJax not always rendering with Vue filtered list

I'm trying to build a filtered list in Vue with equations rendered with MathJax, and it seems to be having some problems, since the equations renders on the first load, but when I search for terms, some equations render and some don't, I can't understand why.
Basically on the first load, if I type a character in my search bar, everything renders correctly, but when I search more, or erase it and do it again, it doesn't, as you can see in these images:
my Vue code is as follows:
var analisiMatematica = new Vue({
el: '#searcher',
data: {
searchQuery: '',
isResult: false,
results: [],
//json: 'json/analisimatematica.json',
error: ''
},
mounted: function() {
axios.get('./json/analisimatematica.json')
.then(function(response) {
this.results = response.data.Domande;
console.log(this.results);
}.bind(this))
.catch(function(error) {
this.error = error.data;
console.log(error.data);
}.bind(this));
},
methods: {
removeSearchQuery: function() {
this.searchQuery = '';
this.isResult = false;
},
submitSearch: function() {
this.isResult = true;
}
},
computed: {
filteredObj: function() {
var list = [];
this.results.forEach(function(el) {
if(el.domanda.toLowerCase().indexOf(this.searchQuery.toLowerCase()) > -1) {
list.push(el);
}
}.bind(this))
return list;
}
}
});
MathJax is loaded in my html file's <head> like this:
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
}
});
</script>
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML">
</script>
While the vue app section is like this:
<div id="searcher">
<p v-show="error" v-html="error"></p>
<form class="searchForm" v-on:submit.prevent="submitSearch">
<input type="text" name="queryInput" v-model="searchQuery" placeholder="Che domanda cerchi?" #keyup="submitSearch">
<span v-show="searchQuery" class="removeInput" #click="removeSearchQuery">+</span>
</form>
<div class="results" v-show="isResult">
<ul>
<li v-for="result in filteredObj">
<p id="domanda">{{ result.domanda }}</p>
<p id="risposta">{{ result.risposta }}</p>
</li>
</ul>
</div>
</div>
All you need is to trigger MathJax to render again when filteredObj is changed. Watch filteredObj:
watch: {
filteredObj: function () {
if ('MathJax' in window) {
this.$nextTick(function() {
MathJax.Hub.Queue(["Typeset",MathJax.Hub, document.body])
});
}
}
}
var analisiMatematica = new Vue({
el: '#searcher',
data: {
searchQuery: '',
isResult: false,
results: [],
//json: 'json/analisimatematica.json',
error: ''
},
mounted: function() {
this.results = [{domanda: '$a+b=c$', risposta: '$a+b=c$'}]
},
methods: {
removeSearchQuery: function() {
this.searchQuery = '';
this.isResult = false;
},
submitSearch: function() {
this.isResult = true;
}
},
computed: {
filteredObj: function() {
var list = [];
this.results.forEach(function(el) {
if(el.domanda.toLowerCase().indexOf(this.searchQuery.toLowerCase()) > -1) {
list.push(el);
}
}.bind(this))
return list;
}
},
watch: {
filteredObj: function () {
if ('MathJax' in window) {
this.$nextTick(function() {
MathJax.Hub.Queue(["Typeset",MathJax.Hub, document.body])
});
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
}
});
</script>
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML">
</script>
<div id="searcher">
<p v-show="error" v-html="error"></p>
<form class="searchForm" v-on:submit.prevent="submitSearch">
<input type="text" name="queryInput" v-model="searchQuery" placeholder="Che domanda cerchi?" #keyup="submitSearch">
<span v-show="searchQuery" class="removeInput" #click="removeSearchQuery">+</span>
</form>
<div class="results" v-show="isResult">
<ul>
<li v-for="result in filteredObj">
<p id="domanda">{{ result.domanda }}</p>
<p id="risposta">{{ result.risposta }}</p>
</li>
</ul>
</div>
</div>

modifying data variable in vue.js using axios

Here is my script :
<html>
<script src="https://unpkg.com/vue"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.0/axios.js"></script>
<body>
<div id="app-3">
<span v-if="seen">{{ textFromApi }}</span>
</div>
<br/>
<script type="text/javascript">
var app3 = new Vue({
el: '#app-3',
data: {
seen: true,
textFromApi: "hello"
},
methods: {
getData() {
return axios.get('https://jsonplaceholder.typicode.com/posts/1')
},
},
created: function () {
this.textFromApi = this.getData();
}
})
</script>
</body>
</html>
I'm trying to modify this.textFromApi from the call of this api: https://jsonplaceholder.typicode.com/posts/1
but my this.textFromApi doesn't seems to update, any ideas why?
Here is a fiddle code:
https://jsfiddle.net/bussiere/5t3v013o/
Edited from remark just below
Regards and thanks
created() is a lifecycle hook, it should be at the same level as data, methods, computed etc. Not a child of methods (so if you nest created() in methods() it will never get executed unless you call the method).
You also don't do anything with the axios promise, you should process it using then ().
<script src="https://unpkg.com/vue"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.0/axios.js"></script>
<body>
<div id="app-3">
<span v-if="seen">{{ textFromApi }}</span>
</div>
<br/>
<script type="text/javascript">
var app3 = new Vue({
el: '#app-3',
data () {
return {
seen: true,
textFromApi: { title: 'empty'}
}
},
methods: {
getData() {
return axios.get('https://jsonplaceholder.typicode.com/posts/1').then(response => {
this.textFromApi = response.data
})
},
},
created: function () {
this.getData();
}
})
</script>
</body>
</html>

Watched prop callback of a component inside a v-if statement is not called

I have a component, "cmptest", which have a watched property, "needWatch".
This component is inside a v-if statement, but the watched function is not called when it is rendered.
As shown in the example, the "needWatch" prop is setted with "value" data property from "cmpcheck", what makes me expect that the watch callback should be fired here.
If I remove the v-if statement, the function is called as expected when the checkbox is clicked.
<div v-if="value===true"><!--remove-->
<cmptest :need-watch="value"></cmptest>
</div><!--remove-->
Is this by design? What am I doing wrong here?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="vue.js"></script>
<script type="text/x-template" id="cmptesttemplate">
<div>
<p>needWatch: {{needWatch}}</p>
<p>updateByWatch: {{updateByWatch}}</p>
</div>
</script>
<script type="text/x-template" id="cmpchecktemplate">
<div>
<input id="checkBox" type="checkbox" value="1" v-on:click="setCheckboxValue()">
<div v-if="value===true">
<cmptest :need-watch="value"></cmptest>
</div>
</div>
</script>
</head>
<body>
<div id="container">
<cmpcheck></cmpcheck>
</div>
<script>
var cmptest = Vue.component('cmptest', {
template: '#cmptesttemplate',
data: function() {
return {
updateByWatch: ''
}
},
props: ['needWatch'],
watch: {
needWatch: function(v) {
console.log('Watched!');
this.updateByWatch = Math.random();
}
}
});
var cmpcheck = Vue.component('cmpcheck', {
template: '#cmpchecktemplate',
data: function() {
return {
value: 'Unitialized'
};
},
methods: {
setCheckboxValue: function() {
console.log('SELECTED');
var el = $(this.$el).children('#checkBox').is(':checked');
this.value = el;
}
}
});
new Vue({
el: '#container',
components: {
'cmptest': cmptest,
'cmpcheck': cmpcheck
}
});
</script>
</body>
</html>
Well, as long as value is Unitialized (thus, not true), <cmptest :need-watch="value"></cmptest> will never be rendered, so the watcher does not actually exist. Once setCheckboxValue is called, if value is true, the cmptest will be rendered and then the watcher initialized. But value is already true, so it's not triggered.
However, you can use:
watch: {
needWatch: {
immediate: true,
handler(nv, ov) { ... }
}
}
so that your watcher callback runs when needWatch is initiated.

Categories

Resources