When I click the nuxt js button the response appears - vue.js

I want to hide the responses of a nuxt js project and post requests with SSR.
This is possible when the page first loads.
<template>
<p v-if="$fetchState.pending">Fetching mountains...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<h1>Nuxt Mountains</h1>
<ul>
<li v-for="mountain of mountains">{{ mountain.title }}</li>
</ul>
<b-btn #click="$fetch">Refresh</b-btn>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>
However, when the button is clicked, apiler appears in the browser network response.
when the page loads
Clicking the button

The reason the request doesn’t appear in the network tab on page load is because nuxt runs the fetch method on the server, and injects the response in to the page component before it loads. You want a button on that same page to fetch the data again, but you don’t want the data request to appear in the network tab?
If so, I think you’re going to have to refresh the page. That way, the fetch method runs again before the page loads, and your user won’t see the request, just like in a traditional SSR app. However this seems like an unusual use case for a Nuxt app!
Instead of:
<b-btn #click="$fetch">Refresh</b-btn>
Use:
<b-btn #click="this.$router.go()”>Refresh</b-btn>

Related

Vue/Nuxt: trying to understand SSR

I've used Vue as a client-side library for years but I unfortunately never dove into server-side rendering, or understand it much, for that matter. I was watching a few tutorials on it where it gave an example of normal client-side fetching with the mount() hook.
<template>
<div v-for="item in items">
<div> {{ item.name }} </div>
</div>
</template>
data() {
return {
items: []
}
}
mount() {
fetch('http://www.myendpoint.com')
.then(response => {
this.items = response;
}
}
vs using Nuxt's asyncData option instead:
<template>
<div v-for="item in items">
<div> {{ item.name }} </div>
</div>
</template>
asyncData() {
fetch('http://www.myendpoint.com')
.then(response => {
this.items = response;
}
}
does this just mean that async data would run long before mountwould ever run since it's run before the component is even loaded so the data will be ready? What happens if that fetch call takes a while to load then...doesn't the same side effect happen? Rather than a component without data ready usingmount()` if the fetch takes long, you'd just have nothing at all loaded until the fetch completes if using SSR?
Nuxt is basically a Vue app but with some server logic done before serving the SPA.
Here are the 2 ways of using some data fetching hooks in Nuxt:
fetch() (it's actual hook's name, nothing related to the fetch API), I do recommend to use this one
asyncData (pretty much the same but less flexible although can block the page render until all the data is properly fetched)
More info can be found between both here: https://nuxtjs.org/docs/2.x/features/data-fetching
A whole question is available here too: Difference between Asyncdata vs Fetch
Lastly, you probably saw the lifecyle for Vue: https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
Here is the one of Nuxt, which adds a bit more layers to Vue's SPA only ones: https://nuxtjs.org/docs/2.x/concepts/nuxt-lifecycle

How to embed LinkedIn Profile in VueJs Component

I am using VueJS to build a website and I got to the point where I want to include my embedded profile into a page/Component in Vue. It seems to work only if I refresh the page. When I navigate from other pages to this page it is not displayed.
In my public/index.html I included LinkedIn Library Script
<script type="text/javascript" src="https://platform.linkedin.com/badges/js/profile.js" async defer></script>
In my component:
<template>
<!-- some other code -->
<div class="col-md-4 col-sm-12 text-sm-center">
<div class="LI-profile-badge" data-version="v1" data-size="medium" data-locale="en_US" data-type="vertical" data-theme="dark" data-vanity="nicolae-orlov">
</div>
</div>
</template>
I saw some info that I need to reload the component to force it to re-render but I am not sure how. Any help is much appreciated.
If you want to add a script tag only on a specific component, you can use PostScribe to render a script after load.
After installing (npm i postscribe --save) and importing (import postscribe from 'postscribe'), you can add your script tag in the mounted lifecycle hook:
mounted() {
postscribe('#linkedin', '<script src="https://platform.linkedin.com/badges/js/profile.js"><\/script>')
}
where #linkedin refers to the ID of your profile badge element (add an ID if necessary)
Your linkedin badge should now be embedded in your Vue component.
You can add the javascript by injecting script into head and then adding the html into the respective component. This is how you can inject javascript directly into head from the component.
<script>
export default {
head(){
return{
script : [
{
src:
'https://platform.linkedin.com/badges/js/profile.js',
type:
'text/javascript'
}
],
}
}
}
</script>

Refresh application route model after login with ember octane

I have an application template with a sidebar component. This sidebar component is passed the application route model to display in a list. The application route checks if the user is authenticated, and if not, skips the model load. The index route is not a protected route, so it will still display when not logged in, just with no user specific data. When the user logs in or attempts to use a protected route, they are redirected to a login route and back to the attempted route transition or index.
There doesn't appear to be any way to force the application route's model hook to refresh after login. I've tried moving the data load in the application route out to a service and calling a refresh method on the service from the login route, but that resulted in the same issue.
So, my main question is what is the recommended approach to loading data after login that is needed in the application template? Is my only option to move this sidebar component to another template that is only accessible after login? This feels harder than it should be, so I am assuming I'm missing some basic concepts here with data flow between routes/components! Thanks!
My Application Route (app/routes/application.js)
import Route from "#ember/routing/route";
import { inject as service } from "#ember/service";
export default class ApplicationRoute extends Route {
#service router;
#service session;
model() {
if (this.get('session').get('isAuthenticated'))
{
return this.store.findAll("project");
}
}
}
Application Template (app/templates/application.hbs)
<HeadLayout />
<div class="wrapper">
<SideBar #projects={{this.model}} />
<div id="content">
<NavBar />
<div>
{{outlet}}
</div>
</div>
</div>
Sidebar component (app/components/side-bar.hbs)
<nav id="sidebar">
<div class="container">
<div class="sidebar-content">
...
{{#if this.session.isAuthenticated}}
<div class="sidebar-projects">
...
<div class="list-group">
{{#each this.projects as |project|}}
<button type="button">
{{project.name}}
</button>
{{/each}}
</div>
</div>
{{else}}
<p>Login to access projects.</p>
{{/if}}
</div>
</div>
</nav>
My router (app/router.js)
import EmberRouter from '#ember/routing/router';
import config from './config/environment';
export default class Router extends EmberRouter {
location = config.locationType;
rootURL = config.rootURL;
}
Router.map(function() {
this.route('login');
this.authenticatedRoute('projects', { path: '/projects'}, function() {
this.authenticatedRoute('new');
this.authenticatedRoute('edit');
this.authenticatedRoute('project', { path: ':project_id' });
});
this.authenticatedRoute('photos', { path: '/photos'}, function() {
this.authenticatedRoute('photo', {path: ':photo_id'});
});
});
You can use the authenticationSucceeded event on the session service and then call refresh. So I think this constructor for your Route can do the trick:
constructor() {
super(...arguments)
this.session.on('authenticationSucceeded', () => this.refresh());
}

How to implement the navigating action of right click menu in Vue?

I am building a demo app, used for handling data. There is a lot of actions available. So I decide to implement a quick menu, which navigate the user to the detail panel, using the right click menu.
I try to use vue-router to mark all function with a unique path, like /action/info, /action/merge. But it turns out to be lack of management.
Are there any good way to solve it?
Vue-router makes sense to use if your actions demand a full screen. Otherwise, you can use a simple dialogue. But if you don't want to consider each action as a separate page, I see two options:
Option 1: You can use full-screen dialogues: you can show them without changing the route.
Option 2: You can use alternative navigation component that navigates without routes. It's not necessary to use it for the whole app. You can use it only for the page where you call all your actions. For example, take a look at v-ons-navigator from Onsen UI. It doesn't use routes, but a stack:
// Go to the "main" page by Vue-router and use v-ons-navigator inside to navigate
// between actions.
<template id="main">
<v-ons-navigator swipeable
:page-stack="pageStack"
#push-page="pageStack.push($event)"
></v-ons-navigator>
</template>
<template id="page">
<v-ons-page>
<v-ons-toolbar>
<div class="center">Page</div>
</v-ons-toolbar>
<p style="text-align: center">
This is the page
<v-ons-button #click="push">Action!</v-ons-button>
</p>
</v-ons-page>
</template>
<template id="action">
<v-ons-page>
<v-ons-toolbar>
<div class="left">
<v-ons-back-button>Page</v-ons-back-button>
</div>
<div class="center">Action!</div>
</v-ons-toolbar>
<p style="text-align: center">This is the page of the action</p>
</v-ons-page>
</template>
const action = {
key: 'action',
template: '#action'
};
const page = {
key: 'page',
template: '#page',
methods: {
push() {
// Here you go to the page of your action.
// You just push it in the stack without changing the route.
this.$emit('push-page', action);
}
}
};
const main = {
template: '#main',
data() {
return {
pageStack: [page]
}
}
};

How can I disable back button on the browser with vue component?

My vue component like this :
<template>
<span class="rating">
...
</span>
</template>
<script>
export default {
props: {
'star': null
},
...
}
</script>
If the component is running I want to disable button back in the browser. So the user can not go back to the previous page
How can I do it?
Try this script, by adding in your html file, where you creat vue instance
history.pushState(null, null, location.href);
window.onpopstate = function () {
history.go(1);
};
Run this code whenever url changes. It will counteract user's back action
window.history.forward(1)