HTML code:
<img src="images/website/image.svg" alt="" width="150px" height="150px" v-on:click="submitimage($event)">
and want to pass the src url of the image to data passing it through $event to a Vue method.
vue script code:
<script>
export default {
data(){
return {
imgurl: ''
}
},
methods: {
submitimage(event){
var element = event.target;
var id = element.getAttribute('src');
window.console.log(id)
this.imgurl = id
},
},
}
</script>
I also tried:
methods: {
submitimage(event){
this.imgurl = this.event.target.getAttribute('src');
window.console.log(event.target.getAttribute('src'))
},
But it works with window.console.log and shows the correct URL, but if I try it to pass it to data(), its not working.
No error, its just empty or undefined.
What am I missing?
It looks like everything your are doing is correct:
check this stackblitz here: https://stackblitz.com/edit/vue-tu7vzx
So I guess it is really the question how you are trying to access this.imgurl
However, your question does not show enough code to make an educated guess.
I want to create my own iron-ajax element, that does what iron-ajax does but a little more, add some headers to the request, at the moment I always add the header via data-binding to the headers property of iron-ajax but I dont want to code that on every element I build, I want the iron-ajax Element to do this by itself.
Is there a way to extend iron-ajax?
Edit:
<template>
<iron-ajax
auto
url="[[url]]"
handle-as="json"
debounce-duration="1000"
on-response=""
headers="[[headers]]"
></iron-ajax>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'em-ajax',
properties: {
headers: {
type: Object,
computed: 'computeHeaders(token)'
},
token: {
type: String,
notify: true,
value: "asdf"
},
url: {
type: String
}
},
computeHeaders: function() {
return {'Authorization' : 'Bearer {' + app.accessToken + '}'};
},
handleRequest: function(request) {
console.log("handling request", request);
request.header = this.computeHeaders();
}
});
})();
</script>
<em-ajax
url="http://api.asdf.safd.sdf/profile"
on-response="handleProfile"
></em-ajax>
How can I handle the on-response? Passing a String with the method name does not seem to work.
The Answer I marked is correct. For my edited question I found a solution:
this.fire('em-response', {event: event, request: request});
I fire an event in my custom ajax Element, and in the element I use the custom ajax element I added a listener. Is this a good solution?
You can embed <iron-ajax> into your own <fancy-ajax> component and forward properties in and out between <fancy-ajax> and <iron-ajax>.
<dom-module id="fancy-ajax">
<template>
<iron-ajax ...></iron-ajax>
</template>
</dom-module>
I'm struggling to understand how to pass data between components in vue.js. I have read through the docs several times and looked at many vue related questions and tutorials, but I'm still not getting it.
To wrap my head around this, I am hoping for help completing a pretty simple example
display a list of users in one component (done)
send the user data to a new component when a link is clicked (done) - see update at bottom.
edit user data and send it back to original component (haven't gotten this far)
Here is a fiddle, which fails on step two: https://jsfiddle.net/retrogradeMT/d1a8hps0/
I understand that I need to use props to pass data to the new component, but I'm not sure how to functionally do it. How do I bind the data to the new component?
HTML:
<div id="page-content">
<router-view></router-view>
</div>
<template id="userBlock" >
<ul>
<li v-for="user in users">{{user.name}} - <a v-link="{ path: '/new' }"> Show new component</a>
</li>
</ul>
</template>
<template id="newtemp" :name ="{{user.name}}">
<form>
<label>Name: </label><input v-model="name">
<input type="submit" value="Submit">
</form>
</template>
js for main component:
Vue.component('app-page', {
template: '#userBlock',
data: function() {
return{
users: []
}
},
ready: function () {
this.fetchUsers();
},
methods: {
fetchUsers: function(){
var users = [
{
id: 1,
name: 'tom'
},
{
id: 2,
name: 'brian'
},
{
id: 3,
name: 'sam'
},
];
this.$set('users', users);
}
}
})
JS for second component:
Vue.component('newtemp', {
template: '#newtemp',
props: 'name',
data: function() {
return {
name: name,
}
},
})
UPDATE
Ok, I've got the second step figured out. Here is a new fiddle showing the progress: https://jsfiddle.net/retrogradeMT/9pffnmjp/
Because I'm using Vue-router, I don't use props to send the data to a new component. Instead, I need set params on the v-link and then use a transition hook to accept it.
V-link changes see named routes in vue-router docs:
<a v-link="{ name: 'new', params: { name: user.name }}"> Show new component</a>
Then on the component, add data to the route options see transition hooks:
Vue.component('newtemp', {
template: '#newtemp',
route: {
data: function(transition) {
transition.next({
// saving the id which is passed in url
name: transition.to.params.name
});
}
},
data: function() {
return {
name:name,
}
},
})
-------------Following is applicable only to Vue 1 --------------
Passing data can be done in multiple ways. The method depends on the type of use.
If you want to pass data from your html while you add a new component. That is done using props.
<my-component prop-name="value"></my-component>
This prop value will be available to your component only if you add the prop name prop-name to your props attribute.
When data is passed from a component to another component because of some dynamic or static event. That is done by using event dispatchers and broadcasters. So for example if you have a component structure like this:
<my-parent>
<my-child-A></my-child-A>
<my-child-B></my-child-B>
</my-parent>
And you want to send data from <my-child-A> to <my-child-B> then in <my-child-A> you will have to dispatch an event:
this.$dispatch('event_name', data);
This event will travel all the way up the parent chain. And from whichever parent you have a branch toward <my-child-B> you broadcast the event along with the data. So in the parent:
events:{
'event_name' : function(data){
this.$broadcast('event_name', data);
},
Now this broadcast will travel down the child chain. And at whichever child you want to grab the event, in our case <my-child-B> we will add another event:
events: {
'event_name' : function(data){
// Your code.
},
},
The third way to pass data is through parameters in v-links. This method is used when components chains are completely destroyed or in cases when the URI changes. And i can see you already understand them.
Decide what type of data communication you want, and choose appropriately.
The best way to send data from a parent component to a child is using props.
Passing data from parent to child via props
Declare props (array or object) in the child
Pass it to the child via <child :name="variableOnParent">
See demo below:
Vue.component('child-comp', {
props: ['message'], // declare the props
template: '<p>At child-comp, using props in the template: {{ message }}</p>',
mounted: function () {
console.log('The props are also available in JS:', this.message);
}
})
new Vue({
el: '#app',
data: {
variableAtParent: 'DATA FROM PARENT!'
}
})
<script src="https://unpkg.com/vue#2.5.13/dist/vue.min.js"></script>
<div id="app">
<p>At Parent: {{ variableAtParent }}<br>And is reactive (edit it) <input v-model="variableAtParent"></p>
<child-comp :message="variableAtParent"></child-comp>
</div>
I think the issue is here:
<template id="newtemp" :name ="{{user.name}}">
When you prefix the prop with : you are indicating to Vue that it is a variable, not a string. So you don't need the {{}} around user.name. Try:
<template id="newtemp" :name ="user.name">
EDIT-----
The above is true, but the bigger issue here is that when you change the URL and go to a new route, the original component disappears. In order to have the second component edit the parent data, the second component would need to be a child component of the first one, or just a part of the same component.
The above-mentioned responses work well but if you want to pass data between 2 sibling components, then the event bus can also be used.
Check out this blog which would help you understand better.
supppose for 2 components : CompA & CompB having same parent and main.js for setting up main vue app. For passing data from CompA to CompB without involving parent component you can do the following.
in main.js file, declare a separate global Vue instance, that will be event bus.
export const bus = new Vue();
In CompA, where the event is generated : you have to emit the event to bus.
methods: {
somethingHappened (){
bus.$emit('changedSomething', 'new data');
}
}
Now the task is to listen the emitted event, so, in CompB, you can listen like.
created (){
bus.$on('changedSomething', (newData) => {
console.log(newData);
})
}
Advantages:
Less & Clean code.
Parent should not involve in passing down data from 1 child comp to another ( as the number of children grows, it will become hard to maintain )
Follows pub-sub approach.
I've found a way to pass parent data to component scope in Vue, i think it's a little a bit of a hack but maybe this will help you.
1) Reference data in Vue Instance as an external object (data : dataObj)
2) Then in the data return function in the child component just return parentScope = dataObj and voila. Now you cann do things like {{ parentScope.prop }} and will work like a charm.
Good Luck!
I access main properties using $root.
Vue.component("example", {
template: `<div>$root.message</div>`
});
...
<example></example>
A global JS variable (object) can be used to pass data between components. Example: Passing data from Ammlogin.vue to Options.vue. In Ammlogin.vue rspData is set to the response from the server. In Options.vue the response from the server is made available via rspData.
index.html:
<script>
var rspData; // global - transfer data between components
</script>
Ammlogin.vue:
....
export default {
data: function() {return vueData},
methods: {
login: function(event){
event.preventDefault(); // otherwise the page is submitted...
vueData.errortxt = "";
axios.post('http://vueamm...../actions.php', { action: this.$data.action, user: this.$data.user, password: this.$data.password})
.then(function (response) {
vueData.user = '';
vueData.password = '';
// activate v-link via JS click...
// JSON.parse is not needed because it is already an object
if (response.data.result === "ok") {
rspData = response.data; // set global rspData
document.getElementById("loginid").click();
} else {
vueData.errortxt = "Felaktig avändare eller lösenord!"
}
})
.catch(function (error) {
// Wu oh! Something went wrong
vueData.errortxt = error.message;
});
},
....
Options.vue:
<template>
<main-layout>
<p>Alternativ</p>
<p>Resultat: {{rspData.result}}</p>
<p>Meddelande: {{rspData.data}}</p>
<v-link href='/'>Logga ut</v-link>
</main-layout>
</template>
<script>
import MainLayout from '../layouts/Main.vue'
import VLink from '../components/VLink.vue'
var optData = { rspData: rspData}; // rspData is global
export default {
data: function() {return optData},
components: {
MainLayout,
VLink
}
}
</script>
I am firing a method :
this.transitionTo('route', {},{search: this.state.search, type: this.state.type});
which passes query params in URL http://...route?search=%param10&type=param2
Is there equivalent method that passes these parameters without printing in URL ??
Try this:
this.transitionTo("route", { search: this.state.search, type: this.state.type });
I'm using AngularUI's ui-select2 directive with AJAX.
Here's what I've got in my view:
<label>Group: <input ng-model="group" ui-select2="select2GroupConfig"></label>
Here's what I have in my model:
$scope.select2GroupConfig = {
ajax: {
url: 'theURL',
data: function (term, page)
{
return { q: term };
},
results: function (data, page)
{
return { results: data };
}
}
};
This works as expected.
My question: How can I update the value via the model?
I tried:
$scope.group = 'some group';
I also tried using an object:
$scope.group = { id: 32, text: 'some group'};
but that doesn't either work.
How do you update a select2 that uses AJAX, via the model?
Turns out you can set it to an object, but only after ui-select2 runs; I was trying to give it an initial value.
So, instead of using the regular model, you have to use select2's initSelection function:
$scope.group = 'Dummy Content';
$scope.select2GroupConfig.initSelection = function ( el, fn ) {
fn({ id: 2, text: 'Some group' });
}
Note that you have to give the input an initial value, otherwise initSelection is never called. That's why I'm just setting it to some dummy content.
This works, but it feels like a hack.
Does anybody have any better ideas?
If you have initSelection setup, you can pass just the ID and the directive will pull up the entire row object.
This will also allow you to set the value when the page loads to just the ID too.
If you don't want to use initSelection you can set the entire row (object) as the value and select2 will update accordingly. It all depends on your use-case however.