Get the calling element with vue.js - javascript

I want to get the calling html element in vue.js to modify it via jQuery. For now I give every element the class name + the index and call it via jQuery afterwards, but this looks like a crazy hack.
What I want to do:
new Vue({
el: "#app",
data: {
testFunction : function(element) {
$(element).doSomethingWithIt(); //do something with the calling element
}
}
});
This is the calling element:
<div v-on:click="testFunction(???)">Test</div>
What can I pass into the function to get the div-element or is there another way to achieve this?

You could get the element from the event like this:
new Vue({
el: "#app",
methods: {
testFunction : function(event) {
$(event.target).doSomethingWithIt();
}
}
});
And then:
<div v-on:click="testFunction">Test</div>
Or (if you want to pass another parameter):
<div v-on:click="testFunction($event)">Test</div>
[demo]

Youre doing it the wrong way.
new Vue({
el: "#app",
data: {
testFunction : function(element) {
$(element).doSomethingWithIt(); //do something with the calling element
}
}
});
data is the state or storage of data for your app.
you need to create methods object for your methods
new Vue({
el: "#app",
data: {
},
methods: {
testFunction : function(element) {
$(element).doSomethingWithIt(); //do something with the calling element
}
}
});

You want v-el to be able to run jQuery on it. For example:
<div v-on:click="testFunction" v-el:my-element>Test</div>
then:
// as noted by #vistajess
// your function should be in the methods object
// not the data object
methods: {
testFunction : function() {
$(this.$els.myElement).doSomethingWithIt();
}
}

Related

is there a way to change the function name of the click event?

I need to change the method name inside v-on:click="function1",
but when I hardcode function1 inside the html, button works and function1 executes but when I pass the "function1" attribute thruogh the Vue's data property, the button does not work and the function1 does not execute. please help me. thanks
button type="button" v-on:click="obj.continueButton" class="btn">Continue</button>
var test = new Vue({
el: "#app",
data: {
obj : {
continueButton: 'function1'
}
(Edited an earlier answer which was incorrect)
You could try it this way instead:
<button type="button" v-on:click="execFn(obj.continueButton)" class="btn">
Continue
</button>
...
data: {
obj: {
continueButton: 'function1'
}
},
methods: {
execFn(name) {
this[name]();
},
function1() {
// do something
},
function2() {
// do something else
}
}

Is there any way to have multiple Vues have a computed listener working on the same value?

Setup:
I have multiple Vue components, and each component has multiple instances in different dialogs in my web app.
For each type of component I have a global state (handrailOptions in the example below) so that each type of component stays in sync across the dialogs.
I'd like for it so that when a component proceeds beyond step 1, I hide the other components in that dialog.
I have achieved this nicely using the computed / watch combo.
However, my problem is that it seems if I try to listen in with computed through more than 1 Vue instance, it hijacks the other listeners.
Problem
Below is a simplified version of what I'm working with, when the app starts up, the console logs 'computed 1' & 'computed 2'. But then when I change handrailOptions.step, only the second fires. ('computed 2' & 'watched 2')
Is there any way to have multiple Vues have a computed listener working on the same value?
handrailOptions = {
step: 1
};
Vue.component( 'handrail-options', {
template: '#module-handrail-options',
data: function() {
return handrailOptions;
},
});
var checkoutDialog = new Vue({
el: '#dialog-checkout',
computed: {
newHandrailStep() {
console.log('computed 1');
return handrailOptions.step;
}
},
watch: {
newHandrailStep( test ) {
console.log('watched 1');
}
}
});
new Vue({
el: '#dialog-estimate-questions',
computed: {
newHandrailStep() {
console.log('computed 2');
return handrailOptions.step;
}
},
watch: {
newHandrailStep( test ) {
console.log('watched 2');
}
}
});
This works as expected. I made handrailOptions responsive by making the data object of a new Vue. Making it the data object of a component, as you did, could also work, but the component would have to be instantiated at least once. It makes more sense to have a single object for your global, anyway.
handrailOptions = {
step: 1
};
// Make it responsive
new Vue({data: handrailOptions});
var checkoutDialog = new Vue({
el: '#dialog-checkout',
computed: {
newHandrailStep() {
console.log('computed 1', handrailOptions.step);
return handrailOptions.step;
}
},
watch: {
newHandrailStep(test) {
console.log('watched 1');
}
}
});
new Vue({
el: '#dialog-estimate-questions',
computed: {
newHandrailStep() {
console.log('computed 2', handrailOptions.step);
return handrailOptions.step;
}
},
watch: {
newHandrailStep(test) {
console.log('watched 2');
}
}
});
setInterval(() => ++handrailOptions.step, 1500);
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="dialog-estimate-questions">
Main step {{newHandrailStep}}
</div>
<div id="dialog-checkout">
CD step {{newHandrailStep}}
</div>

How i can add click handler function to dynamically link in Vue?

Here in Vue component I receive dynamically message from server:
module.exports = {
data() {
return: { windowText: '' }
},
methods: {
showCancelEntrieWindow(){
this.$http.post('/page', {'number' : '123'})
.then(response => {
responseText = response.data.message;
this.windowText = responseText.replace(
new RegExp("class='action'", 'g'),
'v-on:click="myclick"'
);
});
},
myclick(){
console.log('clicked!');
}
}
};
Message have a link with class="action".
As example:
response.data.message = 'Some text... <a class="action" href="/test">test</a>';
In template:
<div v-html="windowText"></div>
How I can add some click handler function to this link?
I am trying to edit response.data.message with replace function like this:
this.windowText = responseText.replace(
new RegExp("class='action'", 'g'),
'v-on:click.stop="myclick"'
);
But it does not work.
Please help me.
And ofcourse, I can't edit response.data.message.
v-html will not compile the template, so replacing the class with the Vue directive will not do anything.
You can, however, use a native event listener.
new Vue({
el: "#app",
data:{
windowText: null,
someValueSetOnClick: null
},
methods:{
onHtmlClick(event){
// Check to make sure this is from our v-html because
// we don't want to handle clicks from other things in
// the Vue
if (!event.target.classList.contains("action"))
return;
event.stopPropagation();
event.preventDefault();
this.someValueSetOnClick = "Clicked";
}
},
mounted(){
this.windowText = 'Some text... <a class="action" href="/test">test</a>'
// Add a native event listener to the Vue element.
this.$el.addEventListener("click", this.onHtmlClick)
}
})
Example.

Vue.js with laravel 5.3

I'm using Laravel 5.3 with Vue.js(very new to this).
Here's my current code
app.js
var vm = new Vue({
el: '#app',
data: {
messages: []
},
ready: function(){
this.getMessages();
},
methods: {
getMessages: function(){
this.$http.get('api/messages').then((response) => {
this.$set('messages', data);
}, (response) => {
});
}
}
});
api.php route is very simple
Route::get('/messages', function() {
return Message::latest()->get();
});
Note: here when i try access the route directly as localhost:8000/api/messages i get the array with the full data
On my view i have
<div class="content" id="app">
<tr v-for="message in messages">
<td> #{{ message}} </td>
</tr>
</div>
I have included online libraries for all jquery, vue.js, and vue.resource.
When i use vue.js debugger it shows that it returns messages[] but it's empty.
I have followed a lot of examples but couldn't get it to work.
Any help is greatly appreciated
if you are using vue.js 2.0 , ready is deprecated now, you may use mounted instead
mounted: function () {
this.$nextTick(function () {
this.getMessages();
})
}
Vue.js Docs
Since you are using the arrow syntax, then I switched to full ES2015 Code
getMessages() {
this.$http.get('api/messages')
.then( result => {
this.messages = result.json()
})
}
Try this:
var vm = new Vue({
el: '#app',
data: {
messages: []
},
ready: function(){
this.getMessages();
},
methods: {
getMessages: function(){
let ctrl = this;
this.$http.get('api/messages').then((response) => {
this.messages = response.data;
});
}
}
});

Backbone LayoutManager Re-Render SubViews

I'm using BBB with the great LayoutManager for the views.
Unfortunately, i can't find a way to re-render specific subviews. Here is my setting:
Home.Views.Layout = Backbone.Layout.extend({
template: "home/home",
el: "#main",
views: {
"#left-menu-container": new Home.Views.Leftmenu(),
"#searchbox": new Home.Views.Searchbox(),
"#content": new Home.Views.Content()
}
});
Home.HomeView = new Home.Views.Layout();
Home.HomeView.render();
Home.Views.AddEditPatient = Backbone.View.extend({
template: "......",
events: {
'click .dosomething': 'dosomething'
},
dosomething: function(){
// [dosomething]
// Only Render Sub-View, e.g. #content here...
}
});
I don't want to re-render the whole layout, what would be possible by calling Home.HomeView.render() again, but how can i render only the sub-view in this setting?
I think you want to add to do something like this with backbone.layoutmanager
thisLayout.setView("#content", new View()).render();
The backbone.layoutmanager v0.6.6 documentation might be helpful
http://documentup.com/tbranyen/backbone.layoutmanager/#usage/nested-views
Also check
http://vimeo.com/32765088
If I understand your question correctly, you can do this in your dosomething function:
this.$("#divToRenderTo").html(new subView().render().$el);
Be sure to have "return this;" at the end of your sub-view's render function.
There are two ways I generally do this with layoutmanager:
Instantiate views in your initialize function and then drop them into the view in beforeRender. This gives your view access to the subview so you can render it directly.
initialize: function() {
this.subview = new SubView();
},
beforeRender: function() {
this.insertView(this.subview);
},
doSomething: function() {
this.subview.render();
}
You can use view.getView(#selector) to return the embedded view and then call render on that.
doSomething: function() {
this.getView('#content').render();
}

Categories