I'm having a issue while using vue router. When I click on the Navbar to change between views/pages, the website works fine, but when I try to go directly to a specific page through the domain/url, I get an error through Firebase (where the website is hosted) saying that the file does not exist in the root index.html.
Here's the code of the index.js file from routes:
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import Courses from "../views/Courses.vue";
import LandingPageTechSession from "../views/LandingPageTechSession.vue";
import VueMeta from "vue-meta";
Vue.use(VueMeta);
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/muddy-match",
name: "MuddyMatch",
component: MuddyMatch,
},
{
path: "/courses",
name: "Courses",
component: Courses,
},
{
path: "/techsession",
name: "TechSession",
component: LandingPageTechSession,
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
export default router;
Here's the code of the App.vue:
<div id="app">
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.2.0/css/all.css"
integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ"
crossorigin="anonymous"
/>
<navbar></navbar>
<router-view />
<bottom></bottom>
</div>
</template>
<script>
import Navbar from "./components/Navbar.vue";
import Bottom from "./components/Footer.vue";
export default {
name: "App",
components: {
Navbar,
Bottom,
},
};
And the Navbar item. (The courses route is with router-link but it still gives the same error):
<template>
<b-container fluid>
<b-navbar toggleable="sm" id="navbar" type="light">
<b-navbar-brand :to="{ name: 'Home' }">
<img id="logo" src="../assets/S2Plogo.png" alt="S2Plogo" />
</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" class="collapse" is-nav>
<b-navbar-nav align="end" class=" ml-auto">
<b-nav-item size="sm" class="navbar-item"
><router-link class="navbar-item" :to="{ path: 'Courses' }">{{
$t("nav.courses")
}}</router-link>
</b-nav-item>
<b-nav-item
size="sm"
class="navbar-item"
:to="{ name: 'TechSession' }"
>{{ $t("nav.techsessions") }}</b-nav-item
>
<b-nav-item
size="sm"
class="navbar-item"
href="https://teespring.com/"
target="_blank"
>{{ $t("nav.merchandise") }}</b-nav-item
>
<b-nav-item size="sm" class="navbar-item" href="/#contact-us">{{
$t("nav.contactus")
}}</b-nav-item>
<b-nav-item
size="sm"
v-on:click="switchLocale()"
class="navbar-item"
>{{ displayLocale }}</b-nav-item
>
</b-navbar-nav>
</b-collapse>
</b-navbar>
</b-container>
</template>
Thank you advance guys!
The answer about this has nothing to do with Vue Router or Vue actually, but with Firebase.
If you want to be able to navigate through url directly, just add the "rewrites" array on your firebase.json:
{
"hosting": {
"public": "dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
},
}
You shouldn't have any issue now.
Happy coding!
It seems like the issue you're facing is connected to the vue-router history mode.
mode: "history",
When using createWebHistory(), the URL will look "normal," e.g. https://example.com/user/id. Beautiful!
Here comes a problem, though: Since our app is a single page client side app, without a proper server configuration, the users will get a 404 error if they access https://example.com/user/id directly in their browser. Now that's ugly.
Not to worry: To fix the issue, all you need to do is add a simple catch-all fallback route to your server. If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in. Beautiful, again!
Please find more details in the documentation of vue-router: vue-router history mode
Hope this helps!
Related
I'm trying to connect my app with facebook login. currently i'm using the developer environment under meta developers account.
I have a login component which looks like below -
import Image from "next/image"
import { signIn } from "next-auth/react"
function Login() {
return (
<div className="grid place-items-center">
<Image
src="https://upload.wikimedia.org/wikipedia/commons/4/44/Facebook_Logo.png?20170210095314"
width={300}
height={300}
style={{objectFit:"contain"}}
alt="logo"
/>
<h1
className="p-5 m-5 bg-blue-500 rounded-full text-white text-center cursor-pointer"
onClick={signIn}>Login with Facebook</h1>
</div>
)
}
export default Login
and here is my code from [...nextauth.js]
import NextAuth from "next-auth"
import FacebookProvider from "next-auth/providers/facebook";
export const authOptions = {
providers: [
FacebookProvider({
clientId: process.env.FACEBOOK_CLIENT_ID,
clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
}),
],
}
export default NextAuth(authOptions)
When i click on login with facebook button it throws error
Any help .....
If anyone encountered the same problem below solution works for me.
I made a silly mistake. The Problem was with NEXT_AUTH_URL.
The url was pointing to https://localhost:3000 which is creating the issue.
I have updated url to http://localhost:3000.
And everything working fine.
I am creating an Admin Dashboard with vitejs, vue3 and vue-router. Exists 2 different templates for all views:
Views having a sidebar:
/buildings
/users
/companies
View with a full-width where the user can login or signup:
/login
/signup
Each component is render in the App.vue file with a sidebar:
<template>
<div class="grid grid-cols-6">
<div class="bg-blue-400">
<ul>
<li><router-link to="/buildings">Buildings</router-link></li>
<li><router-link to="/companies">Companies</router-link></li>
</ul>
</div>
<div class="col-span-5">
<div class="p-10">
<router-view/>
</div>
</div>
</div>
</template>
However, for /login view I need to display a different template because there is no reason to display a sidebar with links in a login form. Because both cases differ in template format, how can I use different templates for a unique router but for different views? Many thanks for considering my request.
I have tried Nested routes, but I am forced to changing all my routes to uses children key, for example:
// Routes dashboard
{
path: '/admin',
component: TemplateWithSidebar, // template 1
children: [
{
path: 'companies',
component: CompaniesView,
}
]
},
// Routes for login
{
path: '/l',
component: TemplateWithoutSidebar, // template 2
children: [
{
path: 'login',
component: LoginView,
}
]
},
Then my App.vue was changed to:
<template>
<div>
<router-view/>
</div>
</template>
I am not experienced enough to determinates if this practice is valid for a production environment o weather exists another best alternative.
first of all my configuration:
nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
// if you want to use static HTML generation (SSG)
target: 'static',
// if you want to use server-side rendering (SSR)
ssr: true,
css: [
'assets/scss/main.css',
'assets/scss/header.css',
'#fortawesome/fontawesome-svg-core/styles.css'
],
build: {
transpile: [
'#fortawesome/vue-fontawesome',
'#fortawesome/fontawesome-svg-core',
'#fortawesome/pro-solid-svg-icons',
'#fortawesome/pro-regular-svg-icons',
'#fortawesome/free-brands-svg-icons'
]
}
})
/plugins/fontawesome.js
import { defineNuxtPlugin } from '#app';
/** Fontawesome for Nuxt 3
* https://fontawesome.com/docs/web/use-with/vue/use-with#nuxt
*
*/
// import the fontawesome core
import { library, config } from '#fortawesome/fontawesome-svg-core'
// import font awesome icon component
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome'
// import specific icons
import { fas } from '#fortawesome/free-solid-svg-icons'
// This is important, we are going to let Nuxt worry about the CSS
config.autoAddCss = false
export default defineNuxtPlugin((nuxtApp) => {
console.log('[Plugin]', 'Font Awesome')
// You can add your icons directly in this plugin. See other examples for how you
// can add other styles or just individual icons.
library.add(fas);
nuxtApp.vueApp.component('font-awesome-icon', FontAwesomeIcon)
})
<template>
<header class="header">
<Logo />
coffee <font-awesome-icon icon="fas coffee" />
flag <font-awesome-icon icon="fas fa-flag" />
search <font-awesome-icon icon="fas fa-magnifying-glass" />
search 2 <font-awesome-icon icon="fa-solid fa-magnifying-glass" />
<nav>
<nuxt-link :to="{ path: '/' }">
Home
</nuxt-link>
<nuxt-link :to="{ path: '/getting-started' }">
Getting Started
</nuxt-link>
<nuxt-link :to="{ path: '/faq' }">
FAQ
</nuxt-link>
<nuxt-link :to="{ path: '/search' }">
<font-awesome-icon icon="fas fa-magnifying-glass" />
</nuxt-link>
</nav>
</header>
</template>
Problem
When I start npx nuxi dev and look at the page via localhost, the icons appear for 1 second and then are no longer visible. I have been searching for a solution for quite some time because I could not find an error right away.
Warning - console
[Vue warn]: Hydration node mismatch:
- Client vnode: font-awesome-icon
- Server rendered DOM: <svg class="svg-inline--fa fa-magnifying-glass" style aria-hidden="true" focusable="false" data-prefix="fas" data-icon="magnifying-glass" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">…</svg>
at <Navigation>
at <Default >
at <AsyncComponentWrapper >
at <BaseTransition mode="out-in" appear=false persisted=false ... >
at <Transition name="layout" mode="out-in" >
at <Anonymous>
at <App key=1 >
at <NuxtRoot>
You can wrap the component in a <client-only>, so it only renders client-side.
<client-only>
<font-awesome-icon icon="fas fa-flag" />
</client-only>
I am working with bootstrap 4 and angular 7, I have the following element, which function is to hide/show a sidebar.
<a
class="app-sidebar__toggle"
href="#"
data-toggle="sidebar"
aria-label="Hide Sidebar"
></a>
The problem is when I enter to specific route, this reloads all page. These are my routes in app-routing.module.ts
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'catalogo/lista', component: CatalogoListaComponent },
{ path: '', redirectTo: 'home', pathMatch: 'full' }
];
So, if I enter to http://localhost:4200/home, the error will happen, but if I enter to any other route (my default empty route will redirect to /home), for example, http://localhost:4200 or http://localhost:4200/a_route_that_not_exists, I am redirected to /home (as expected), and the button that show/hide the sidebar works well.
I hope to be clear in my problem and I would like a lot you can help me.
EDIT: More code of my application...
This is my app.component.html:
<app-header></app-header>
<app-sidebar></app-sidebar>
<div class="app-content">
<app-title [titulo]="titulo" [icono]="icono [breadcrumbs]="breadcrumbs"></app-title>
<router-outlet></router-outlet>
</div>
This is my header.component.html (where I use the link to show/hide the sidebar):
<header class="app-header">
<a class="app-header__logo" href="index.html">Vali</a>
<!-- Sidebar toggle button-->
<a
class="app-sidebar__toggle"
href="#"
data-toggle="sidebar"
aria-label="Hide Sidebar"
></a>
<p>.... more html</p>
</header>
And this is my sidebar.component.html:
<div class="app-sidebar__overlay" data-toggle="sidebar"></div>
<aside class="app-sidebar">
<div class="app-sidebar__user">
<img
class="app-sidebar__user-avatar"
src="https://s3.amazonaws.com/uifaces/faces/twitter/jsa/48.jpg"
alt="User Image"
/>
<div>
<p class="app-sidebar__user-name">John Doe</p>
<p class="app-sidebar__user-designation">Frontend Developer</p>
</div>
</div>
<ul class="app-menu">
<li>
<a class="app-menu__item" [routerLink]="['/home']">
<i class="app-menu__icon fa fa-home"></i>
<span class="app-menu__label">Inicio</span>
</a>
</li>
more menu elements...
<ul>
</aside>
Generally a lot of the Popper/ JS elements in Bootstrap won't work out of the box in Angular; Angular provides a pretty solid way to handle elements like sidenavs.
Since the element you want to use to toggle the sidenav doesn't exist in the same component as the sidenav, you can set up a basic service that handles the sidenav state. To create your sidenav service (run in console in your project root):
ng g s sidenav
And then in the generated sidenav.service.ts:
import {Injectable} from '#angular/core';
import {BehaviorSubject} from 'rxjs';
#Injectable()
export class SidenavService {
public isOpen: boolean = false;
public toggleChange: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor() {}
public toggle(): void {
this.isOpen = !this.isOpen;
this.toggleChange.next(this.isOpen);
}
}
In your header.component.html you can modify the clickable element that will show/ hide the sidebar:
<a
class="app-sidebar__toggle"
aria-label="Hide Sidebar"
(click)="toggleSidebar()"
></a>
In your header.component.ts file you can then set toggleSidebar() to run the toggle() function in the service you just set up:
import {SidenavService} from "[wherever your service is located]";
#Component({ /*...*/ })
export class HeaderComponent {
constructor(private sidenavService: SidenavService)
toggleSidebar(): void {
this.sidenavService.toggle();
}
}
You can then (in either your app component or sidebar component) set up reacting to the toggle:
//assuming you're in sidebar.component.ts
import {SidenavService} from "[wherever your service is located]";
import {OnInit, OnDestroy} from "#angular/core";
import {Subscription} from "rxjs";
#Component({ /*...*/ })
export class SidebarComponent implement OnInit, OnDestroy {
isOpen: boolean;
sidenavSubscription: Subscription;
constructor(private sidenavService: SidenavService) {}
ngOnInit() {
this.sidenavSubscription = this.sidenavService.toggleChange.subscribe(isOpenChange => {
this.isOpen = isOpenChange;
});
}
ngOnDestroy() {
this.sidenavSubscription.unsubscribe();
}
}
You can then use the isOpen variable in your sidebar component in different ways to control sidebar activity. Examples include using an [ngClass] directive:
<!--in your header component-->
<header [ngClass]={'active': isOpen, 'inactive': !isOpen} >
</header>
Or you can build in something using angular animations to animate the sidebar in and out (using ngIf and the :enter/ :leave transitions).
I am trying to implement firebase google login in my AngularDart project but while implementing angular dart throws an error. I have rechecked for the *ngIftypo but unable to find the needful required.
Kindly help me with this thank you.
Error running TemplateGenerator for
my_app|lib/views/layout_component/layout_component.dart.
Error: Template parse errors:
line 32, column 35 of LayoutComponent: ParseErrorLevel.FATAL: Can't bind to
'ngIf' since it isn't a known native property or known directive. Please fix
typo or add to directives list.
*ngIf="fbService.user == null"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
line 32, column 17 of LayoutComponent: ParseErrorLevel.FATAL: Property
binding ngIf not used by any directive on an embedded template
<div id="sign-in" *ngIf="fbService.user == null" class="horiz">
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
line 37, column 36 of LayoutComponent: ParseErrorLevel.FATAL: Can't bind to
'ngIf' since it isn't a known native property or known directive. Please fix
typo or add to directives list.
*ngIf="fbService.user != null"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
line 37, column 17 of LayoutComponent: ParseErrorLevel.FATAL: Property
binding ngIf not used by any directive on an embedded template
<div id="sign-out" *ngIf="fbService.user != null" class="horiz">
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app_component.dart
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
import 'package:your_next_startup/views/layout_component/layout_component.dart';
import 'package:your_next_startup/services/firebase_service.dart';
#Component(
selector: 'my-app',
styleUrls: const ['app_component.css'],
templateUrl: 'app_component.html',
directives: const [
materialDirectives,
LayoutComponent,
],
providers: const [
materialProviders,
FirebaseService,
],
)
class AppComponent {
final FirebaseService fbService;
AppComponent(FirebaseService this.fbService);
}
layout_component.dart
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
import 'package:m_app/services/firebase_service.dart';
#Component(
selector: 'app-layout',
styleUrls: const [
'layout_component.css',
],
templateUrl: 'layout_component.html',
directives: const [
materialDirectives,
],
providers: const [
FirebaseService,
],
)
class LayoutComponent {
final FirebaseService fbService;
LayoutComponent(FirebaseService this.fbService);
}
layout_component.html
<div class="horiz">
<div id="sign-in" *ngIf="fbService.user == null" class="horiz">
<div id="google-icon" class="icon"></div>
<button class="btn btn-outline-secondary btn-sm" (click)="fbService.signIn()">Google Sign In</button>
</div>
<div id="sign-out" *ngIf="fbService.user != null" class="horiz">
<img class="icon" [src]="fbService.user?.photoURL">
<div id="user-name">{{fbService.user?.displayName}}</div>
<button class="btn btn-outline-secondary btn-sm" (click)="fbService.signOut()">Sign Out</button>
</div>
</div>
That doesn't seem to be related to firebase.
#Component(
selector: 'app-layout',
styleUrls: const [
'layout_component.css',
],
templateUrl: 'layout_component.html',
directives: const [
materialDirectives,
NgIf, // one of these two
COMMON_DIRECTIVES, // this one includes NgIf, NgFor, NgSwitchCase, ...
],
providers: const [
FirebaseService,
],
)
class LayoutComponent {
final FirebaseService fbService;
LayoutComponent(FirebaseService this.fbService);
}
In Angular 3 and earlier directives could be registered in pubspec.yaml for the whole application, this isn't supported anymore and all used directives need to be registered in the components annotation where they are used.