Vue.js dynamic array in template not working - javascript

I just started fiddling with VueJs and I tried a simple example where an array has values and use it in a template, it works just fine
<body>
<div id="app">
{{operations.join(', ')}}
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Understanding Hooks',
operations: ['One', 'Two'],
}
})
</script>
However, when I tried to populate operations(array) dynamically page/browser becomes unresponsive (following is the code). Any inputs would be helpful.
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Undstanding Hooks',
operations: ['One', 'Two'],
},
created: function() {
console.log('=> ', this.operations)
this.operations.push('CREATED : ');
},
mounted: function() {
this.operations.push('MOUNTED : ');
},
updated: function() {
this.operations.push('UPDATED : ');
},
destroyed: function() {
this.operations.push('DESTROYED : ');
},
})
</script>

Updated
this.operations.push('UPDATED : '); will make component updated hooks run infinite. Please try removing it.
And there is a best practice about immutable and reactive . Reference of this.operations is not changed.
You should use
this.operations = [...this.operations, 'CREATED : ']
instead of
this.operations.push('CREATED : ');
or
this.operations = this.operations.concat(['CREATED :'])

Related

trigger event on a bootstrap switch with VueJS 2

I deal with a boostrap switch
In JQuery, it is easy, you can do as doc state:
$('input[name="my-checkbox"]').on('switchChange.bootstrapSwitch', function(event, state) {
console.log(this); // DOM element
console.log(event); // jQuery event
console.log(state); // true | false
});
But in VueJS, I can't bind the element to value:
<div id="vue-instance">
<input type="checkbox" name="my-checkbox" checked #click="log">
</div>
var vm = new Vue({
el: '#vue-instance',
data: {
},
methods:{
log(){
alert('ok');
}
},
mounted(){
$("[name='my-checkbox']").bootstrapSwitch();
}
});
Here is the fiddle: https://jsfiddle.net/xoco70/tfkLkLqw/1/
If you really need to use this, you can simply bind to the change on the mounted life-cycle hook.
var vm = new Vue({
el: '#vue-instance',
data: {
},
methods:{
log(event, state){
alert('ok');
}
},
mounted(){
$("[name='my-checkbox']").bootstrapSwitch();
$('input[name="my-checkbox"]').on('switchChange.bootstrapSwitch', this.log.bind(this));
}
});
I say If you really need to use this because you are mixing the data driven approach of Vue.js with querying the view with JQuery. I also tried coming up with a solution where you could use a Vue binding so you could react to events or changes in the model, but it seems the library does not update the value of the html input when the toggle is switched.
Working Example
var vm = new Vue({
el: '#vue-instance',
data: {
bSwitch: null
},
methods:{
log(event, state){
this.bSwitch = state;
console.log('switch to state ' + state );
}
},
mounted(){
$("[name='my-checkbox']").bootstrapSwitch();
$('input[name="my-checkbox"]').on('switchChange.bootstrapSwitch', this.log.bind(this));
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/bootstrap-switch#3.3.4/dist/js/bootstrap-switch.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<link href="https://unpkg.com/bootstrap-switch#3.3.4/dist/css/bootstrap3/bootstrap-switch.css" rel="stylesheet"/>
<div id="vue-instance">
Switch State: {{bSwitch}}
<br>
<input type="checkbox" name="my-checkbox">
</div>

Dynamically binding title tag in vuejs

I'm new to vuejs.
I try to bind data on the title tag dynamically. I used vue-head to do this on a simple html page. I do not use webpack and npm.
This is how I bind the title tag :
var app = new Vue({
el: 'html',
head: {
title: function () {
return {
inner: this.remaining + ' Tâches',
separator: ' ',
complement: ' '
}
}
}
In the vue-head documentation, they suggest to do this :
methods: {
getAsyncData: function () {
var self = this
window.setTimeout(function () {
self.title = 'My async title'
self.$emit('updateHead')
}, 3000)
}
},
I also tried to set it in the watch prop, but it didn't work.
Here is my entire code : https://jsfiddle.net/5d70s0s6/1/
Thanks
Use a computed property.
computed: {
title: {
get() {
document.title = this.remaining
return this.remaining
},
set(val) {
document.title = val
}
}
}
You don't need to use <title>{{title}}</title>. If you change title in your Vue, it will be applied automatically to the page.
Also, you should not bind a Vue instance to html, head or body tags. Use regular elements only like <div id="app"></div> and set your Vue el: '#app'
Or you could use this:
data: {
title: '',
},
watch: {
title(val) {
document.title = val
}
}
Update:
While the code above can solve your problem. I created this tiny vue-title component that can be used in your project easily.
Example:
<vue-title>{{title}}</vue-title>

Update dynamic MathJax with Vuejs 2?

P.S: Now i know how to fix this. bind data with v-html
<div id="app">
<h1 v-html="math"></h1>
<button #click='change'>Change</button>
</div>
var vm = new Vue({
el: '#app',
data: function() {
return {
math: '`sum`'
}
},
methods : {
change : function() {
this.math = '`a '+Math.floor((Math.random() * 10) + 1)+'`';
this.$nextTick(function() {
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
});
}
}
})
When i update data, it duplicate element ???
I dont know why, how to update MathJax with vuejs 2 ?
This is my app: Image
var vm = new Vue({
el: '#app',
data: function() {
return {
math: 'sum'
}
},
methods : {
change : function() {
this.math = 'sum_'+Math.floor((Math.random() * 10) + 1);
this.$nextTick(function() {
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
});
}
}
})
You could replace the entire contents of the MathDiv element and call MathJax.Hub.Typeset(), but there is a more efficient approach, which is to ask MathJax for the element jax for the mathematics, and call its method for replacing the formula shown by that element. So the updated code will look like:
<div id="app">
<h1 >{{ math }}</h1>
<button #click='change'>Change</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: function() {
return {
math: '`sum_1`'
}
},
mounted: function () {
this.$nextTick(function () {
MathJax.Hub.Typeset()
})
},
methods : {
change : function() {
this.math = 'sum_'+Math.floor((Math.random() * 10) + 1);
this.$nextTick(function() {
var math = MathJax.Hub.getAllJax("MathDiv")[0];
MathJax.Hub.Queue(["Text", math, this.math]);
});
}
}
})
</script>
Refer: http://docs.mathjax.org/en/latest/advanced/typeset.html#manipulating-individual-math-elements
OR
You could use v-html to bind the data to the element.

Run component method on load vue.js

hey I'm pretty new to Vue.js and I'm trying to accomplish what seems to be a simple thing but I'm, having trouble. Essentially, I need it so every time a component is loaded into the DOM, one of it's methods fire. Here is my current code, I've tried to use v-on:load but it doesn't seem to work.
Vue.component('graph', {
props:['graphId','graphData'],
template: '<canvas v-on:load="{{populateGraph()}}"></canvas>',
methods: {
initGraph: function () {
var settlementBalanceBarChart = new Chart(this.graphId, {
type: "bar",
data: settlementBalanceBarData,
options: settlementBalanceBarOptions
});
},
//this is the function I would like to run
populateGraph: function () {
alert('{{graphId}}');
}
}
});
var vm = new Vue({
el: "#app",
mounted: function(){
}
});
The same code functions fine if I use the v-on:click event
There are instance lifecycle hooks that you can use for that. For example:
Vue.component('graph', {
props:['graphId','graphData'],
template: '<canvas></canvas>',
created: function () {
alert('{{graphId}}');
},
methods: {}
});
You have to call the function prefixed by "this" as following:
var data =
{
cashiers: []
}
var vm = new Vue({
el: '#app',
data: data,
created: function () {
this.getCashiers();
},
methods: {
getCashiers: function () {
vm.cashiers = [];
}
}
});

Javascript / vue.js receive json

I'm trying to receive json in my vue.js app like this:
new Vue({
el: 'body',
data:{
role: '',
company: '',
list:[],
created: function() {
this.getJson();
},
methods: {
getJson: function(){
$.getJSON('http://domain.dev/data',function(task){
this.list = task;
}.bind(this));
}
}
}
});
But the result is null? When I test this in postman the url returns json. What am I doing wrong here?
EDIT:
JSON (testdata):
{"EmployeeId":1,"RoleId":5,"DepartmentId":6,"InternId":1,"FirstName":"Zoe","LastName":"Altenwerth","Bio":"Quidem perferendis.","email":"Kole.Bechtelar#hotmail.com","LinkedIn":"Sterling.Schowalter#example.net","Gender":0,"password":"$2y$10$bbUlDh2060RBRVHSPHoQSu05ykfkw2hGQa8ZO8nmZLFFa3Emy18gK","PlainPassword":"gr^S=Z","remember_token":"D528C0Ba1Xzq3yRV7FdNvDd8SYbrM0gAJdFUcOBq4sNEJdHEOb2xIQ0geVhZ","Address":"0593 Dallin Parkway Apt. 499\nBotsfordborough, MT 12501","Zip":"21503-","City":"East Janiston","ProfilePicture":null,"BirthDate":"2002-10-13 00:00:00","StartDate":"1995-11-09 21:42:22","EndDate":"2011-01-27","Suspended":0,"created_at":"2016-02-29 12:21:42","updated_at":"2016-03-02 11:53:58","deleted_at":null,"role":{"RoleId":5,"RoleName":"Superadministrator","Description":"Mag administrators toevoegen en bewerken","deleted_at":null,"created_at":"-0001-11-30 00:00:00","updated_at":"-0001-11-30 00:00:00"},"department":{"DepartmentId":6,"CompanyId":12,"DepartmentName":"com","Description":"Accusantium quae.","deleted_at":null,"created_at":"2016-02-29 12:21:41","updated_at":"2016-02-29 12:21:41","company":{"CompanyId":12,"CompanyName":"Dare, Bailey and Bednar","Logo":null,"Address":"85762 Tabitha Lights\nWest Jettie, AK 20878-2569","Zip":"29601","City":"Traceside","KvKNumber":"84c70661-9","EcaboNumber":"fdee61e3-a22d-3332-a","deleted_at":null,"created_at":"2016-02-29 12:21:41","updated_at":"2016-02-29 12:21:41"}}}
Here is a little example of how to load external JSON data into your component:
a.json:
{"hello": "welcome"}
index.html:
<div id="app">
<pre>{{ json.hello }}</pre>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
json: null
}
});
$.getJSON('http://localhost/a.json', function (json) {
app.json = json;
});
</script>
--- Edited ---
Or with created event:
<script type="text/javascript">
new Vue({
el: '#app',
data: {
json: null
},
created: function () {
var _this = this;
$.getJSON('http://localhost/a.json', function (json) {
_this.json = json;
});
}
});
</script>
Building on #vbarbarosh's answer, but using the browser's fetch api:
a.json:
{"hello": "welcome"}
index.html:
<div id="app">
<pre>{{ json.hello }}</pre>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
json: null
},
created: function () {
fetch("/a.json")
.then(r => r.json())
.then(json => {
this.json=json;
});
}
});
</script>
You have to bind this to the outer function, too.
getJson: function () { ...}.bind(this)
Update for Vue3
const app = Vue.createApp({
data: function() {
return {
role: '',
company: '',
list:[]
};
},
beforeMount: function() {
this.getJson();
},
methods: {
getJson: function(){
$.getJSON('http://domain.dev/data',function(task){
this.list = task;
}.bind(this));
}
}
});
const mountedApp = app.mount('body');

Categories

Resources