Vue - rendering templates after Ajax call - ajax

I have a page which loads some information chunks at the beginning and it loads other ones when user scroll down. In this chunks I have also , for which I have a function written.
Simplified structure of the chunk looks like that:
<div class="chunk_class">
<div class="chunk_header">
<div class="title"></div>
<div class="subtitle"></div>
</div>
....
<div class="actions">
<comparison-training-toggle training-id="70" init-comparison="0" icon="n-compare" class="v-comparison-toggle" title="Some title"></comparison-training-toggle>
<div class="another_action"></div>
</div>
It works for the chunks that I load at page load, but it doesn't work for the other ones that I load through Ajax call. How can I make it work also for Ajax loaded ones? Do I need to install some other modules (I have now installed Vue, Vue-resource & Vue-router)?
Below part of the function that I wrote with comments what does and what doesn't work:
$(document, context).once('vue__comparison_toggle_add').each(() => {
Drupal.behaviors.vue__comparison_toggle.vueComponent(); //this works
});
$(document).ajaxComplete(function(e, xhr, settings){
Drupal.behaviors.vue__comparison_toggle.vueComponent();//it enters the the ajaxComplete, but doesn't work, it still remains <comparison-training-toggle>...
});
},
vueComponent: function () {
Vue.component('comparison-training-toggle', {
template: this.template,
props: ['trainingId', 'icon', 'init-comparison'],
data() {
return {
inComparison: false,
}
},
computed: {
toggleText() {
return this.inComparison ? Drupal.t('Usuń z porównania') : Drupal.t('Dodaj do porównania')
}
},
methods: {
toggle() {
...

Related

Laravel Nova | Arrow functions | computed property not working in Tool.vue

I have a computed property that is not working correctly. When reading the docs this is how it should be done for Vue 2.x. The code i have:
<template>
<div>
<button :disabled="isDisabled">Import configurator data</button>
<input class="input" type="file" id="file" v-on:change="setFile">
</div>
</template>
<script lang="js">
export default {
data: () => {
return {
importDisabled: true,
}
},
computed: {
isDisabled() {
return this.importDisabled;
},
},
methods: {
setFile: (e) => {
this.importDisabled = false;
},
}
}
</script>
Expected behaviour: Button enables when a file is selected.
Actual behaviour: Button stays disabled.
What am i missing here? A console.log within the isDisabled() methods shows it is only called once. It is not called after importDisabled changes.
Other info:
vue 2.6.12
laravel nova
Also note: Vue tools does not detect a Vue component in the inspector. But the Vue behaviour is working when loading the tool.
It seems arrow functions are bound to the parent context. That was the reason my code did not work. this is then not bound to the Vue instance but the parent (Window) which causes it not to work.
Wrong:
setFile: (e) => {
this.importDisabled = false;
},
Right:
setFile: function() {
this.importDisabled = false;
},
More information:
https://codingexplained.com/coding/front-end/vue-js/using-es6-arrow-functions-vue-js

How to transfer data between components placed in different views

I have two compoennts placed in one the same view.
#extends('layouts.app')
#section('content')
<bus></bus>
<bus2></bus2>
#endsection
I want to pass data (name) from one component to other one after clicking button. To do that I' using $emit function.
/// bus component
<template>
<div>
<p> Name Bus 1{{name}}</p>
<input type="button" #click="setName()" value="s"/>
</div>
</template>
<script>
export default {
created() {},
data: function() {
return {
name: "Volvo"
};
},
methods: {
setName: function(id) {
this.$root.$emit("sname", this.name);
}
},
props: []
};
</script>
///bus 2 component
<template>
<div>
<p> Name bus 2{{name}}</p>
</div>
</template>
<script>
export default {
created() {
this.$root.$on("sname", data => {
this.name = data;
});
},
data: function() {
return {
count: 0,
name: ""
};
},
methods: {}
};
</script>
Everything works fine. Name is transfered from bus to bus2. The problem exists when I place bus2 in different view - data are not transfered but code is the same. How can I transfer data between components placed in different views
Try using Vuex to specify your app state, and mutate this when it's necessary.
Vuex states are accessible from every components using this.$store or $store.

Vuejs Displaying a component multiple times with Axios in it

I have been trying to figure out this for a hours but no luck. I have 2 components. The first component is dynamic and the second component just gets the user geolocation. The geolocation is then displayed in the first component.
My problem is that I display the first component a few times on the page and every time it is displayed it makes a GET request which is inefficient . If I display the component 3 times it will make 3 GET requests.
What would be the best way to rewrite this?
Thanks for the help
Component 1:
<template>
<section id="under-info">
THe user is from <ip_info></ip_info>
</section>
</template>
<script>
export default {
}
</script>
Component 2:
<template>
<span id="user-city">
{{value}}
</span>
</template>
<script>
export default {
mounted: function () {
this.$nextTick(function () {
this.getIpInfo(this.param)
})
},
props:['param'],
data: function () {
return {
value:null
}
},
methods:{
getIpInfo(){
var vm = this
delete axios.defaults.headers.common["X-Requested-With"];
delete axios.defaults.headers.common["X-CSRF-TOKEN"];
axios
.get('http://api.ipstack.com/check?access_key=?',{
timeout: 1000
})
.then(function(response) {
vm.value = response.data['city]
})
}
},
}
</script>
Wrap the code where you want to reuse this value 3x in a component.
<template>
<div>
The user is from {{location}}, and {{location}} is a great place. They have a baseball team in {{location}}
</div>
</template>
<script>
export default {
mounted: function () {
this.$nextTick(function () {
if(this.needLocation){
this.getIpInfo(this.param)
}
})
},
props:['param', 'needLocation'],
data: function () {
return {
location:null
}
},
methods:{
getIpInfo(){
this.location = //results from your API call
}
}
</script>

Laravel router-link works only the first time

I am trying to fetch results from database in News.vue, and display them in Topnews.vue. I have two links fetched. When I click link1, it shows up the Topnews.vue template with everything working as intended, however, if i click link2, nothing happens, except for that the URL changes, but the template does not show up the result. If i refresh the page and click link2 or click on the navbar, then link2, it shows up, and same, clicking then link1, changes the URL, but doesnt show up. I'm really stuck on that and I'd be really glad if you help me out on that issue. Hope you understand.
News.vue
<template id="news">
<div class="col-sm-5">
<div class="cars" v-for="row in filteredNews" >
<div class="name" >
<p class="desc_top_time">{{row.created_at}}</p>
<span class="last_p"> {{row.category}}</span>
<h3 style="margin-bottom:-4px; font-size: 16px;">
<router-link class="btn btn-primary" v-bind:to="{name: 'Topnews', params: {id: row.id} }">{{row.title}}</router-link></h3>
</div></div></div>
</template>
<script>
export default {
data: function() {
return {
news: [],
}
},
created: function() {
let uri = '/news';
Axios.get(uri).then((response) => {
this.news = response.data;
});
},
computed: {
filteredNews: function() {
if (this.news.length) {
return this.news;
}
}
}
}
</script>
Topnews.vue
<template id="topnews1">
<div class="col-sm-7">
<div class="cars">
<img :src="topnews.thumb" class="img-responsive" width=100%/>
<div class="name" ><h3>{{ topnews.title }}</h3>
<p>
<br>{{ topnews.info }}<br/>
</p>
</div></div></div>
</template>
<script>
export default {
data:function(){
return {topnews: {title: '', thumb: '', info: ''}}
},
created:function() {
let uri = '/news/'+this.$route.params.id;
Axios.get(uri).then((response) => {
this.topnews = response.data;
});
}
}
</script>
Like GoogleMac said Vue will reuse the same component whenever possible. Since the route for both IDs use the same component Vue will not recreate it, so the created() method is only being called on the first page. You'll need to use the routers beforeRouteUpdate to capture the route change and update the data.
in TopNews.vue:
export default {
data:function(){
return {topnews: {title: '', thumb: '', info: ''}}
},
beforeRouteEnter:function(to, from, next) {
let uri = '/news/'+ to.params.id;
Axios.get(uri).then((response) => {
next(vm => {
vm.setData(response.data)
})
});
},
beforeRouteUpdate: function(to, from, next) {
let uri = '/news/'+ to.params.id;
Axios.get(uri).then((response) => {
this.setData(response.data);
next();
});
},
methods: {
setData(data) {
this.topnews = data
}
}
}
If you click a link referring to the page you are on, nothing will change. Vue Router is smart enough to not make any changes.
My guess is that the IDs are messed up. If you are using Vue devtools you will be able to easily see what data is in each link. Are they as you expect.

MVC Partial View Returns Whole Page Instead of Just the Partial

I have the following partial view named "_transactions":
<div id="section-transactions" class="documentsanchor">
</div>
<div>
<div class="row">
<div class="col-lg-12">
<div>
<h4 class="company-headings">#ViewBag.SecSymbol Transactions</h4>
</div>
<div>
</div>
</div>
I render it using
#{Html.RenderAction("Transactions", "Company");}
and this is the Transactions method from the Company controller:
public async Task<PartialViewResult> Transactions()
{
ViewBag.SecSymbol = "test";
return PartialView("_transactions");
}
It's on a page with other partial views.
This works fine. However, I have a button on the page that should get a new partial view and replace the current one. It makes an ajax call as follows
$("#btn_transactions").click(function (e) {
var url = "Company/Transactions";
$.ajax({
url: url,
success: function (result) {
alert(result);
$('#transTarget').html(result);
},
error: function () {
alert("Error occured");
}
});
})
The issue is that the whole page is returned in "result", that is, all partials as well as the layout, when all I want is the transactions partial. What am I doing wrong?
Add this code in partial view
#{
Layout=null;
}
Make sure you have the route set up in your configs -
routes.MapRoute("CompanyTransactions", "company/transactions", new { controller = "Company", action = "Transactions" });

Resources