Cant mount children component to ref - vue.js

I have a problem with VuePaginator , that I can mount it to my Vue app $refs properties. I am doing everyting according to docs, here is my component in the html:
<v-paginator :resource.sync="comments" ref="vpaginator" resource_url="{{route('api.item.comments', $item->pk_i_id)}}"></v-paginator>
The pagination works correctly, but I can't trigger fetchData() from the vuejs code, because paginator is not getting mounted to vm.$refs.vpaginator.
Here is the code that I use:
var app = new Vue({
el: '#comments',
data : {
comments: [],
newComment: {
text: ""
}
},
components: {
VPaginator: VuePaginator
},
methods: {
addComment: function(comment){
var vm = this;
this.$http.post($('meta[name="item-url"]').attr('content'), comment)
.then(function(response){
toastr.success(response.data.result);
comment.text = "";
vm.$.vpaginator.fetchData();
}).catch(function (error) {
if(error.data){
toastr.error(error.data.text[0]);
}
})
},
logRefs: function(){
console.log(this.$refs.vpaginator);
}
}
});
I have created logRefs() function to check the $ref property and it is always undefined.

Since you are using the Version 1 of VueJS, usage is a bit different - check this demo http://jsbin.com/rupogesumo/edit?html,js,output
<v-paginator :resource.sync="comments" v-ref:vpaginator resource_url="{{route('api.item.comments', $item->pk_i_id)}}"></v-paginator>
Docs Reference: https://v1.vuejs.org/api/#v-ref

Related

Show Image EXIF for User with VueJS

I work with Exif.js and VueJS for my project.
but i have problem.
when i want show information of image on screen it doesn't work.
but it work on Browser Console.
How i show information with tag in html for Users?
Here is my code:
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Vue exif meta info getter',
DateImage: "DateTimeDigitized"
},
components: {
'picture-input': PictureInput
},
methods: {
onChange(image) {
console.log('onChange!')
if (image) {
EXIF.getData(this.$refs.pictureInput.file, function () {
console.log('image info', this)
console.log('exif data', this.exifdata)
console.log("date image jadid : " + this.DateImage);
})
} else {
console.log(`it's not image`)
}
},
getEI() {
var old = console.log;
var logger = document.getElementById('log');
console.log = function (message) {
if (typeof message == 'object') {
logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify(message) : message) + '<br />';
} else {
logger.innerHTML += message + '<br />';
}
}
}
}
})
</script>
you have an issue with data and reactivity. Here the concepts from the vue guide.
"Due to the limitations of modern JavaScript (and the abandonment of Object.observe), Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive."
Means data should be a function for reusability and you need declare a variable for apply the exif values and be capable of show them updated in the screen
Extra, next time include your html part sometimes the errors will be there.
A extra common problem starting with vue is the use of this, well this inside exif it's not the same to this in vue. An easy way for bypass 'this' issue is save the vue this in a temporary variable (let vm = this) and use them inside the exif code.
Just like that:
<template>
<!-- exifs is an object, you can print direct a value
if you know their key (exifs.Name) or you can iterate
with v-for and show all the values -->
<p v-for="ex in exifs">
{{ex}}
</p>
</template>
<script>
const app = new Vue({
el: '#app',
data() {
return {
message: 'Vue exif meta info getter',
DateImage: "DateTimeDigitized",
exifs: null
}
},
components: {
'picture-input': PictureInput
},
methods: {
onChange(image) {
console.log('onChange!')
if (image) {
let vm = this
EXIF.getData(this.$refs.pictureInput.file, function () {
vm.exifs = this
})
} else {
console.log(`it's not image`)
}
},
getEI() {
var old = console.log;
var logger = document.getElementById('log');
console.log = function (message) {
if (typeof message == 'object') {
logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify(message) : message) + '<br />';
} else {
logger.innerHTML += message + '<br />';
}
}
}
}
})
</script>
Here the example you use from jsfiddle fixed

VueJS - function in import js file not getting triggered

We are building a web application using Vue JS and PHP, we are new to Vue JS. The server-side execution is fine, the API is able to fetch data as JSON. While trying out a static array display before making the API call, we find that the function in imported "app.js" is not getting called and the table displayed is empty. Please let us know what we might be doing wrong. Appreciate your help.
import Vue from 'vue';
export const MY_CONST = 'Vue.js';
export let memberList = new Vue({
el: '#members',
data: {
members: []
},
mounted: function () {
this.getAllMembers();
},
methods: {
getAllMembers: function () {
/*
axios.get("https://xxxxxx.com/services/api.php")
.then(function (response) {
memberList.members = response.data.members;
});
*/
memberList.members = [{ "empname": "Dinesh Dassss" },
{ "empname": "Kapil Koranne" }];
}
}
});
This is the Vue component. The members object is empty.
<script>
import * as mykey from './app.js'
export default {
name: 'Home',
props: {
msg: String
},
data() {
return {
message: `Hello ${mykey.MY_CONST}!`,
members: mykey.memberList.members
}
}
};
</script>
You can also use this reference for current instance reference:
getAllMembers: function () {
var me = this;
/*
axios.get("https://xxxxxx.com/services/api.php")
.then(function (response) {
// direct this not works here but we have
//saved this in another variable and scope of a var is there
me.members = response.data.members;
});
*/
// this reference works fine here.
this.members = [{ "empname": "Dinesh Dassss" },
{ "empname": "Kapil Koranne" }];
}

How to call a global component with out HTML tag in Vue?

I want a global dialog component which is called only by JavaScript. And never had custom content within it. So I don't want to put any HTML tag like <my-dialog ref="myDialog"></my-dialog> in my code. Just call this.$ref.myDialog.show().
I have a HTML tag version. How to instance the component only in JavaScript?
I think you neeed to create a JS window with a component inside
here is an example:
var componentName = "my-dialog";
var model = {d:1};
var d = document.createElement("div"); // JavaScript Window
document.body.appendChild(d);
d.id = 'win' + componentName;
var app = new Vue({
render(h, data) {
return h(componentName, { on: { 'close': this.close }, props: { model: this.model } });
},
el: d, data: { wait: false, error: "", after: 0, model },
mounted() {
},
methods: {
close() {
this.$destroy();
$(d).remove(); // remove the window by jQuery
}
}
})
First you need to assign Vue to window.vue.
window.vue = new Vue({ // options })
then call it using js. vue.$ref.myDialog.show()

Cannot access Vue data set within mounted via ajax

I am using Vue2. I am getting json data via ajax in my mounted method. I then set that data to a data variable expecting to be able to access it from other methods outside of mounted, but all I get is an empty observable.
Any suggestions/advice? Thanks for the help.
var vm = new Vue({
el: '#app',
data: function () {
return {
allJson: []
};
},
methods: {
updateTableData: function(isActive) {
// cannot access this.allJson here
}
},
mounted: function() {
$.getJSON(Routes.USERS_GET_JSON, function(json) {
this.allJson = json;
});
}
});
I haven't used jQuery in a long, long time, but if I remember correctly you need to explicitly declare the context of this if you wish to use it within the callback, else you get something unexpected. However, I don't know if $.getJSON supports it even though it's a wrapper. So you can try the following:
$.getJSON(Routes.USERS_GET_JSON, function(json) {
this.allJson = json;
}, {
context: this
})
Or you can use .bind off of the function to scope this
$.getJSON(Routes.USERS_GET_JSON, function(json) {
this.allJson = json
}.bind(this))
Or if you're tranpsiling down with babel (which you probably are) you can use fat arrow syntax:
$.getJSON(Routes.USERS_GET_JSON)
.done( (json) => {
this.allJson = json
})
Or you can just alias this before the $.getJSON
let _self = this
$.getJSON(Routes.USERS_GET_JSON, function(json) {
_self.allJson = json
})
My guess is that this is not bound to your vue instance inside the callback function. Try the following
var vm = new Vue({
el: '#app',
data: function () {
return {
allJson: []
};
},
methods: {
updateTableData: function(isActive) {
// cannot access this.allJson here
}
},
mounted: function() {
const self = this;
$.getJSON(Routes.USERS_GET_JSON, function(json) {
self.allJson = json;
});
}
});

Is it possible to use vue-router without a component in vue 2?

I have a very simple page, just a few lines of code and I would like to use vue-router without a vue-component.
I would like to get the string "my-search-query" after the root:
www.example.com/my-search-query
and use it in my main Vue() object. Is this possible?
Thank you!
It is possible to use vue-router without a vue-component and still be notified about path changes in the main Vue() app object:
You can get the "my-search-query" string from www.example.com/#/my-search-query like this:
const router = new VueRouter({
routes: [
{ path: '/:question' }
]
})
const app = new Vue({
el: '#app',
router,
watch: {
'$route.params.question': function(newVal, oldVal) {
alert(newVal === 'my-search-query');
}
}
});
Thanks to #samayo for pointing me in the right direction!
Since the router is part of your view model instance, you can create a computed function that returns the path value of the router. For example, you can do the following:
data: function() {
router: new VueRouter()
},
computed: function() {
routerPath: function() {
return this.router.currentRoute.path;
}
},
watch: function() {
routerPath: function(val) {
switch(val) {
case '/':
// #TODO: logic for home
break;
case '/path1':
var query = this.router.currentRoute.query;
// #TODO: logic form query params
break;
}
}
}
With this, the router will manage the history for you, but you don't have to divide your code up into components. For example, I have a pretty small page and just wanted to put everything into the same viewModel without breaking everything up into components.
As tom_h has said you can use window.location.pathname if you just want to get the path name. If you want to be notified when this pathname changes, then first initialize it to your data(){} object and watch it as:
data () {
return {
path: window.location.pathname
}
},
watch: {
path (newpath, oldpath) {
alert('location path just changed from ' + newpath + ' to ' + oldpath )
}
}