Refresh page just once after getting response - javascript

I am trying to reload the page after getting the response. But the issue I am facing is that it page reload goes into a loop and reloads continuously. How can I make it reload just once after getting the response.
create.vue
<script>
export default {
data () {
return {
agent: {
full_name: '',
address: '',
}
}
}
created() {
this.fetchAgent();
},
methods: {
fetchAgent() {
this.$axios.get(`/agent.json?${this.$route.query()}`)
.then(response => {
this.agent = response.data;
window.location.reload();
});
},
}
}
</script>

Related

Axios set URL for GET request from the GET request response

This question is very similar to This question
I have set up a Vue page with Laravel and showing all posts with a help of a GET request. I am also listening to a Laravel ECHO event and unshifting the value to the all posts array making it appear on top.
I have set up the infinite scroll and paginating 5 results per page using this package. Results appear on the page and pushing to the array from the listener also works. However, when infinite scroll loads the 2nd results page, the 6th result is duplicated.
The aforementioned package accepts next_cursor an offset value as the parameter instead of page=2 so it exactly loads the value without any duplications.
Controller.php
public function pusherGet(Request $request) {
$jobs = Job::orderBy('id','desc')->cursorPaginate();
return response()->json($jobs);
}
Vue file
<template>
<div>
<h3 class="text-center">All Jobs</h3><br/>
<div class="container">
<div class="card" v-for="(job,index) in jobs" :key="index">
<div class="card-body">
<h4 class="card-title">{{ job.id }}</h4>
<p class="card-text">{{ job.request_type}}</p>
</div>
</div>
</div>
<infinite-loading #infinite="getJob"></infinite-loading>
</div>
</template>
<script>
export default {
data() {
return {
page:1,
jobs: [],
}
},
mounted() {
this.listenNewJobs();
},
created() {
},
methods: {
listenNewJobs() {
Echo.channel('chat-room.1')
.listen('JobCreated', (e) => {
console.log(e);
this.jobs.unshift(e.job);
});
},
getJob($state) {
axios.get('getjobs', {
params: {
page: this.page,
},
}).then(({data})=> {
console.log(data)
if(data.data.length) {
this.page += 1;
this.jobs.push(...data.data)
$state.loaded();
} else {
$state.complete();
}
});
}
}
}
</script>
Results Json
{
data: Array(5), path: "getjobs?page=1", previous_cursor: "100", next_cursor: "96", per_page: 5, …}
data: (5) [{…}, {…}, {…}, {…}, {…}]
next_cursor: "96" // this is the parameter which i should attach to the GET request to paginate correct results
next_page_url: "getjobs?page=1&next_cursor=96"
path: "getjobs?page=1"
per_page: 5
prev_page_url: "getjobs?page=1&previous_cursor=100"
previous_cursor: "100"
__proto__: Object
Any help would be greatly appreciated.
Edit : How to Set the URL for the GET request to paginate the results from the GET request response for paginated results to avoid 2nd page result duplication ?
Try the following:
<script>
export default {
data() {
return {
jobs: [],
isInitialLoaded: false,
currentPage: 1,
lastPage: 0,
}
},
mounted() {
this.listenNewJobs();
},
created() {
//
},
methods: {
listenNewJobs() {
Echo.channel('chat-room.1')
.listen('JobCreated', (e) => {
console.log(e);
this.jobs.unshift(e.job);
});
},
async getJob($state){
await this.fetchData().then((response) => {
this.lastPage = response.data.last_page;
if (response.data.data.length > 0) {
response.data.data.forEach((item) => {
const exists = this.jobs.find((job) => job.id == item.id);
if (!exists) {
// this.jobs.unshift(item); // Add to front of array
this.jobs.push(item);
}
});
if (this.currentPage - 1 === this.lastPage) {
this.currentPage = 2;
$state.complete();
} else {
this.currentPage += 1;
}
$state.loaded();
} else {
this.currentPage = 2;
$state.complete();
}
});
this.isInitialLoaded = true;
},
fetchData() {
const url = this.isInitialLoaded ? `/getjobs?page=${this.currentPage}` : `/getjobs`;
return axios.get(url);
},
}
}
</script>

How to remove external JS when navigate to another page VUEJS

I have java script component in home component with external js. I need to remove external js when page navigate to another page. Page does not refresh.
<script>
function initFreshChat() {
window.fcWidget.init({
token: "***",
host: "https://wchat.freshchat.com"
});
}
function initialize(i,t){var e;i.getElementById(t)?initFreshChat():((e=i.createElement("script")).id=t,e.async=!0,e.src="https://wchat.freshchat.com/js/widget.js",e.onload=initFreshChat,i.head.appendChild(e))}function initiateCall(){initialize(document,"freshchat-js-sdk")}window.addEventListener?window.addEventListener("load",initiateCall,!1):window.attachEvent("load",initiateCall,!1);
</script>
This is the external js: https://wchat.freshchat.com/js/widget.js
I need this because i need to keep this freshchat window in one page.
This can be done by putting any condition. But it will works if we refresh the page. Here pages are not refreshing at all.
Therefore I need to remove the external js when navigate to another pages. And mount back when came to this page.
You can wrap the script in side a Vue component life circle,
render
remove
refresh
whenever you need.
I found this code on codepen https://codepen.io/akccakcctw/pen/LBKQZE
Vue.component("fc-button", {
template: "#fcButton",
props: {
fc: {
type: Object,
default: {},
}
},
methods: {
openWidget: function() {
document.getElementById("fc_frame").style.visibility = "visible";
window.fcWidget.open();
}
}
});
const vm = new Vue({
el: "#app",
data: function() {
return {
fc: {
isInit: false,
},
};
},
mounted: function() {
var self = this;
window.fcSettings = {
token: "8d3a4a04-5562-4f59-8f66-f84a269897a1",
host: "https://wchat.freshchat.com",
config: {
cssNames: {
widget: "custom_fc_frame",
open: "custom_fc_open",
expanded: "custom_fc_expanded"
},
headerProperty: {
hideChatButton: true
}
},
onInit: function() {
window.fcWidget.on("widget:loaded", function() {
self.fc.isInit = true;
window.fcWidget.on("unreadCount:notify", function(resp) {
console.log(resp);
test = resp;
if (resp.count > 0) {
// document.getElementById('notify').classList.add('h-btn-notify');
document.getElementById("notify").style.visibility = "visible";
} else if (resp.count == 0) {
// document.getElementById('notify').classList.remove('h-btn-notify');
document.getElementById("notify").style.visibility = "hidden";
}
});
window.fcWidget.on("widget:closed", function() {
document.getElementById("fc_frame").style.visibility = "hidden";
document.getElementById("open_fc_widget").style.visibility =
"visible";
});
window.fcWidget.on("widget:opened", function(resp) {
document.getElementById("open_fc_widget").style.visibility =
"hidden";
});
});
}
};
}
});

Mitrhil.js conditional routing and authentication

I'm studying javascript and mithril.js 1.1.6. I'm writing down a simple web app in which users land on a page where he can login. Users who already did login land on a different page. I'm trying this using conditional routing, here is the main component:
const m = require("mithril");
...
import Eventbus from './whafodi/eventbus.js';
import WelcomePage from './ui/welcome.js';
import User from './model/user.js';
var eventbus = new Eventbus();
function MyApp() {
return {
usrAuth: function() {
m.route(document.body, "/", {
"/": { view: () => m("p", "hello")}
})
},
usrNotAuth: function() {
m.route(document.body, "/", {
"/": { render: v => m(WelcomePage, eventbus) }
})
},
oninit: function(vnode) {
vnode.state.user = new User();
eventbus.subscribe({
type: "login",
handle: function(action) {
vnode.state.user.token = action.token;
console.log(JSON.stringify(vnode.state.user));
}
});
},
view: function(vnode) {
if(vnode.state.user.token) {
this.usrAuth();
} else {
this.usrNotAuth();
}
}
}
};
m.mount(document.body, MyApp);
MyApp is the main component. It check if user has a token, then return the proper route. This is the component that is in charge to let users login:
const m = require("mithril");
const hellojs = require("hellojs");
function TopBar(node) {
var bus = node.attrs.eventbus;
function _login() {
hellojs('facebook').login({scope:'email'});
}
return {
oninit: function(vnode) {
hellojs.init({
facebook: XXXXXXX,
}, {
redirect_uri: 'http://localhost'
});
hellojs.on('auth.login', auth => {
var fbtoken = auth.authResponse.access_token;
m.request({
method:"POST",
url:"./myapp/login/fb/token",
data:auth.authResponse,
background: true
}).then(function(result){
console.log(result);
bus.publish({ type: "login", token: result.jwttoken });
m.route.set("/");
}, function(error){
console.log(error);
bus.publish({ type: "login", token: "" });
});
});
},
view: function(vnode) {
return m("div", [
m("button", { onclick: _login }, "Login")
]);
}
}
}
export default TopBar;
TopBar component occurs in the WelcomePage component mentioned in the main one. TopBar renders a button and use hello.js to login. It uses the EventBus bus parameter to tell main component user logged in (there is an handler in main component to update the user model). Once user logins, event is fired and main component updates the user model. Good. Now, how can trigger the main component to load the right route?
I read mithril'docs again and I found that RouteResolvers perfectly suit my needs. Here is an example:
var App = (function() {
var login;
function isLoggedIn(component) {
if(login) {
return component;
} else {
m.route.set("/hey");
}
}
return {
oninit: function(vnode) {
EventBus.subscribe({
type: "login",
handle: function(action) {
console.log("incoming action: " + JSON.stringify(action));
login = action.value;
}
});
},
oncreate: function(vnode) {
Foo.eventbus = EventBus;
Bar.eventbus = EventBus;
Hey.eventbus = EventBus;
m.route(document.body, "/hey", {
"/foo": {
onmatch: function(args, requestedPath, route) { return isLoggedIn(Foo); }
},
"/bar": {
onmatch: function(args, requestedPath, route) { return isLoggedIn(Bar); }
},
"/hey": Hey
});
},
view: function(vnode) {
return m("div", "home..");
}
};
})();
Eventbus is used to let components communicate with App. They fire events (login type events) that App can handle. I found convenient to pass Eventbus the way oncreate method shows, I can use Eventbus in each component's oncreate to let components fire events.

Vue.js - search form with query parameters

I am using Vue.js 2.6 with the vue-router component. I have a search form as follows:
<form class="search-form" #submit.prevent="search">
<div class="form-group">
<input type="text" class="form-control" v-model="term" placeholder="Search">
</div>
</form>
And here is my script:
<script>
export default {
data() {
return {
term: this.$route.query.term,
items: []
}
},
created() {
if (this.term != null) {
this.search()
}
},
watch: {
'$route.query.term'() {
this.term = this.$route.query.term
this.search()
}
},
methods: {
search: function () {
window.axios.get('/images/search', {
params: {
term: this.term
}
})
.then(response => {
this.$router.push({query: { 'term' : this.term}})
this.items = response.data.collection.items
})
.catch(error => {
return error
})
}
}
}
</script>
What I am trying to achieve with this code is the following:
User submits form, the search() function is called. The URL is updated with the query param, e.g. /search?term=<term>. This is working but the search() function is being called twice.
User carries out several searches, then presses the back button. The search field in the form is updated and the search is carried out. This is working but the search() function is being called twice.
User manually enters query param in the URL bar. The search field in the form is populated and the search is carried out. This is working.
Where the search() function is being called twice, this is due to the watch() function, which is designed to watch changes to the URL bar. I am not sure how to combine this function correctly with the search() function.
In watch, you can compare new value with old value, and only perform search when new value is different with old value
watch: {
'$route.query.term'(newVal, oldVal) {
if (newVal != oldVal) {
this.term = this.$route.query.term
this.search()
}
}
},
To make it call only 1 for 1st case, you might want to separate button click handler with real search call
<script>
export default {
data() {
return {
term: this.$route.query.term,
items: []
}
},
created() {
if (this.term != null) {
this.performSearch()
}
},
watch: {
'$route.query.term': {
handler: function(newVal, oldVal) {
if (newVal != oldVal) {
this.term = this.$route.query.term
this.performSearch()
}
},
immediate: true
}
},
methods: {
search: function () {
// this is call when user click search Button
this.$router.push({query: { 'term' : this.term}})
},
performSearch() {
// perform actual searcch
window.axios.get('/images/search', {
params: {
term: this.term
}
})
.then(response => {
this.items = response.data.collection.items
})
.catch(error => {
return error
})
}
}
}
</script>

Next page does not open. Problem with pagination

I need to make a pagination in my task, but it is not working.
I made two buttons to which I attached the "click" event and I registered a property in the "data". When I click on the buttons, the property changes and is written to the link and in the same way changes the current 10 posts to the following.
But for some reason it does not work as it should work. Can someone please explain what my mistake is and if you can suggest some articles on the subject of "pagination".
This is my html:
<button type="button" #click="counter -=1" class="prev">Prev</button>
<div class="counter">{{ counter }}</div>
<button type="button" #click="counter +=1" class="next">Next</button>
This is my Vue:
export default {
name: 'app',
data () {
return {
counter: 1,
zero: 0,
posts: [],
createTitle: '',
createBody: '',
visiblePostID: ''
};
},
created () {
axios.get('http://jsonplaceholder.typicode.com/posts?_start=${this.counter}+${this.zero}&_limit=10').then(response => {
this.posts = response.data;
});
}
};
The created method is called only when the component is created. To make the GET request everytime the counter increase or decrease use watches link.
Your example will become:
export default {
name: 'app',
data () {
return {
counter: 1,
zero: 0,
posts: [],
createTitle: '',
createBody: '',
visiblePostID: '',
}
},
watch: {
counter: function(newValue, oldValue) {
this.getData()
}
}
created(){
this.getData()
},
methods: {
getData() {
axios.get(`http://jsonplaceholder.typicode.com/posts?_start=${this.counter}+${this.zero}&_limit=10`).then(response => {
this.posts = response.data
})
}
}
}
You need to create a watcher for your counter that fires a load method. This way every time your counter changes you'll load in the correct posts for the page in your paginated results.
export default {
name: 'app',
data () {
return{
counter: 1,
...
}
},
created(){
this.loadPosts()
},
watch: {
counter(newVal, oldVal){
this.loadPosts()
}
},
methods: {
loadPosts(){
axios.get('http://jsonplaceholder.typicode.com/posts?_start=${this.counter}+${this.zero}&_limit=10')
.then(response => {
this.posts = response.data
})
}
}
}
Maybe this can help you. https://scotch.io/courses/getting-started-with-vue/vue-events-build-a-counter
I don't know vue, but looks like you need a function to load new data

Categories

Resources