When trying to use the Angular 2 Component Router (Angular 2 RC 4) with the upgrade adapter I got the following error:
Bootstrap at least one component before injecting Router. at
setupRouter
This is my main.ts file:
angular.module(moduleName).directive('odetteSecureApp', upgradeAdapter.downgradeNg2Component(OdetteSecureAppComponent));
upgradeAdapter.addProvider(APP_ROUTER_PROVIDERS);
upgradeAdapter.bootstrap(document.body, [moduleName]);
I google the problem and found the following links, but they all correspond to the router deprecated module as the Angular team changed how the router works since RC4:
https://github.com/angular/angular/issues/7147?_pjax=%23js-repo-pjax-container
Any ideas?
To use the RC3 (3.0.0-alpha.*) router, you need to do a couple of things differently from how the router was set up in previous versions.
You need to define a RouterConfig like this:
import {provideRouter, RouterConfig} from '#angular/router';
export const APP_ROUTES : RouterConfig = [
{path: '', component: AppComponent},
// more paths
];
export const APP_ROUTE_PROVIDERS = [
provideRouter(APP_ROUTES)
];
then in your main.ts
upgradeAdapter.addProvider(APP_ROUTER_PROVIDERS);
Resolved by the following official post:
https://github.com/angular/angular/issues/9870
Related
Created a simple Vue project using the CLI:
vue create my-project
Wanted to add two pages, so installed the latest version of vue-router (which is currently v3.4.8) and followed the vue mastery tutorial for routing.
This is what my router.js file looks like:
import { createWebHistory, createRouter } from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: About },
]
})
export default router
And of course, this is what my main.js file looks like:
import { createApp } from 'vue'
import router from './router'
createApp({
template: `
<div>
<router-link to='/'>Home</router-link>
<router-link to='/create'>Create</router-link>
</div>
`
})
.use(router)
.mount('#app')
Both of the Home and About components don't really have much in them, this is what they look like:
<template>
<div>TODO: Home</div>
</template>
<script>
export default {
name: 'Home'
}
</script>
Anyway, all of this to say that I am getting the following error on:
Uncaught TypeError: Object(...) is not a function
at eval (router.js?41cb:5)
This is specifically on createRouter
Have I done something wrong?
Edit: as Boussadjra Brahim pointed out, originally createWebHistory was just being passed in without being a function call. I've since updated the code to include this.
Interestingly enough, once that was done, the error is not happening upon it's call.
This issue is caused when you install Vue router 3 with Vue 3 so you should uninstall the current version :
npm uninstall vue-router --save
and install the new one by :
npm i vue-router#next --save
Example
In my case it was the other way round (I was getting the same error), I had vue 2.6 installed and Vue Router 4, so I had to downgrade Vue Router to 3.5
For vue3 you should install the #4 package with the following command:
npm install vue-router#4
Please consult the following migration guide if you're having problems: Migrating from Vue 2
I am new to Vue and Vuetify. I just created quick app to check both of them. But I am a running into issues in beginning. The vue fails to identify vuetify components despite following all the steps outlined in document. The error is like below -
vue.runtime.esm.js?ff9b:587 [Vue warn]: Unknown custom element:
- did you register the component correctly? For recursive
components, make sure to provide the "name" option.
found in
---> at src\App.vue
You can access the entire code at sandbox https://codesandbox.io/s/40rqnl8kw
You're likely experiencing a problem with the order of your operations. You're defining your own App component that uses the v-app component before you've even told Vue to make use of it, so Vue assumes you're using your own custom v-app component.
Place Vue.use(Vuetify) before starting any Vue instances via new Vue() that require Vuetify components, or place it within the component definitions themselves right at the top of the <script> tag after importing Vue and Vuetify within the single file component. Don't worry if you have more than one Vue.use(Vuetify) statement because only the first one will do anything--all subsequent calls will simply do nothing.
Original - Vue.use() is called before new Vue(), resulting in an error.
new Vue({
el: "#app",
components: { App },
template: "<App/>"
});
Vue.use(Vuetify);
Fix - Calling new Vue() after Vue.use() allows Vue to resolve the dependency correctly.
Vue.use(Vuetify);
new Vue({
el: "#app",
components: { App },
template: "<App/>"
});
There is another reason for this error that I recently ran into.
I recently upgraded from Vuetify 1.5 to 2.x and even though I had the order of operations correct as in the currently accepted answer here I was still receiving the error about v-app being unknown:
Unknown custom element: <v-app> - did you register the component
correctly? For recursive components, make sure to provide the "name"
option.
Turns out that the upgrade process requires the following addition to package.json devDependencies section which didn't originally exist in my vuetify 1.5x package:
"vuetify-loader": "^1.3.0"
(1.3.0 current version as of this writing)
Once I added that the error went away.
If you are coming from Google: for me it was breaking changes from v1 to v2, that made most Codepen examples useless.
I had to change this to get a very simple Vuetify app with navigation drawers to run again:
remove toolbar from <v-app toolbar>
replace v-toolbar with v-app-bar
replace v-app-bar-side-icon with v-app-bar-nav-icon
replace v-app-bar-title with v-toolbar
replace v-list-tile to v-list-item
replace all flat with text
Maybe this helps someone.
(edited to include cong yu's remark)
Edit: it looks like VuetifyLoader will automatcially do that for you.
Old Answer: Another possible problem is if you have a la carte enabled you will need to also specify all the components that you want included:
import Vue from 'vue'
import App from './App.vue'
import Vuetify, {
VApp, // required
VNavigationDrawer,
VFooter,
VToolbar,
VFadeTransition
} from 'vuetify/lib'
import { Ripple } from 'vuetify/lib/directives'
Vue.use(Vuetify, {
components: {
VApp,
VNavigationDrawer,
VFooter,
VToolbar,
VFadeTransition
},
directives: {
Ripple
}
})
With vuetify v2.x you should register the vuetify plugin as follows :
import Vue from 'vue'
/** register vuetify plugin globally **/
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
const opts = {}
const vuetify= new Vuetify(opts)
/****/
new Vue({
vuetify,
}).$mount('#app')
Vuetify v3
import { createApp } from 'vue'
import App from './App.vue'
/*****/
import '#mdi/font/css/materialdesignicons.css'
import 'vuetify/lib/styles/main.sass'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
const vuetify= createVuetify({
components,
directives,
})
/****/
const app = createApp(App)
app.use(vuetify)
app.mount('#app')
I experienced the same issue. It was caused by the cache of the browser make sure to clear the cache as well.
You will get this error even after installing the official Vuetify 3 (Alpha), due to the standard demo version generated during the install lacking adding components, i.e:
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";
const vuetify = createVuetify({
components,
directives,
});
Thus the working version of main.ts for Vuetify 3 is:
import "vuetify/styles"; // Global CSS has to be imported
import { createApp } from "vue";
import { createVuetify } from "vuetify";
import App from "./App.vue";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";
const app = createApp(App);
const vuetify = createVuetify({
components,
directives,
});
app.use(vuetify).mount("#app");
// or app.use(vuetify); app.mount("#app");
In case someone like me new working on vue and nuxt. My mistake was that I did not put the s in the last. buildModule should be buildModules.
My nuxt.config.js:
export default {
buildModules:[
"#nuxtjs/vuetify"
],
module:[
"#nuxtjs/axios"
],
components:true
}
At this project I'm working on there is a legacy server-rendered web page and some components had problems I've been assigned to fix, and I convinced the team to rewrite those parts in Vue to kickstart our migration.
I wrote the whole mini-app using the Webpack template provided by Vue CLI and it works like a charm... in that specific environment.
If I npm run build the built index.html also works fine in a static server.
However, I can't seem to include the app in an existing page composed of many other elements. Shouldn't it be as simple as adding the <div id='myApp'></div> element to the HTML and loading the generated JS files?
If it helps, the legacy app is a Rails app using .erb templates and the JS files are being loaded through the main pipeline in application.js.
Does anyone know why nothing happens when I try this?
Edit: more information - this is how main.js looks before build:
/* eslint-disable */
import Vue from 'vue'
// UI components
import VueSelect from 'vue-select'
import DynamicForm from './components/DynamicForm/'
Vue.component('vue-select', VueSelect)
Vue.config.productionTip = false
const DynamicForms = new Vue({
el: '.dynamic-form',
render: h => h(DynamicForm)
})
Edit: I managed to get Vue to work by integrating Webpack to Rails with Webpacker. However I still have some problems regarding context:
This is my main.js in one of the Vue components. It was working fine until I tried the PropData stunt so I could reuse the component with different data in a few places.
/* eslint-disable */
import Vue from 'vue'
// UI components
import VueSelect from 'vue-select'
// import 'nouislider'
import DynamicForm from './components/DynamicForm/'
import fields from './fields'
import fieldRules from './field-rules'
Vue.component('vue-select', VueSelect)
Vue.config.productionTip = false
document.addEventListener('DOMContentLoaded', () => {
const el = document.createElement('div')
document.querySelector('.dynamic-form').appendChild(el)
const vm = new DynamicForm({
propsData: {
fields,
fieldRules
},
el,
render: h => h(DynamicForm)
})
})
This is DynamicForm/index.vue
<template>
<div id='app'>
<ParamList :fields='paramFields' :fieldRules='paramRules'></ParamList>
<Output></Output>
</div>
</template>
<script>
import Vue from 'vue'
import ParamList from './ParamList'
import Output from './Output'
export default Vue.extend({
props: [ 'fields', 'fieldRules' ],
name: 'DynamicForm',
components: {
ParamList,
Output
},
data () {
return {
paramFields: this.fields,
paramRules: this.fieldRules
}
}
})
</script>
<style>
</style>
The field and fieldData props are merely JSON/JSONP with some data I'm going to use inside those components. The idea is that I could write another main.js changing just the field and fieldData when initing the Vue instance.
What am I doing wrong?
I've managed to fix everything in a three-step change to my components.
Integrate Webpack into Rails using Webpacker. There's even a Vue template!
Change the root component (the one mounted at a real DOM element) to a Vue subclass using Vue.extend (so the module line # the .vue file read export default Vue.extend({ instead of simply export default {
Remove the render function from the new DynamicForm (the name I assigned Vue.extend to) so it renders its own template.
I hope it helps as it was quite a pain to me!
In AngularJS, for routing purposes, we define states with children which makes it possible to switch between views with the result that each view is always rendered in one container:
$stateProvider.state("communication.create-message", {
url: ...,
templateUrl: ...,
menu: ...,
parent: "communication",
ncyBreadcrumb: {
label: "Create Message"
}
});
Whichever state we choose - the view is always rendered within one container that has ui-view attribute.
I'm trying to achieve the same in Angular 2 or above, but I have no idea of how to reproduce the above-stated functionality.
In app.component.ts we have router-outlet where component templates get rendered.
Say, we have many nested child routes - is it possible to render all of them within this outlet ?
What would the code in app-routing.module.ts look like in this case ?
Could anyone please give a working example of how to go about it ?
Step 1 : Import Routes from #angular/router
in app.module.ts .. import Routes. You have to write
import {Routes} from '#angular/core'
Step 2 :
Add all the routes you want to set up in an array pf type Routes like :
this is for informing angular all the routes in your app. Each route is a javascript object in this array.
const appRoutes : Routes = [
{path : 'communication-route'}
]
always you have to give path , this what you enter after your domain like "localhost :4200/communication-route".
Step 3: Add the action to route i.e what happens when this path is reached.
const appRoutes : Routes = [
{path : 'communication-route'} , component :communicationroutecomponent
]
here i have given the component name "communicationroutecomponent" , i.e this component will be loaded when the path "/communication-route" is reached
Step 4: Register your routes in your app
To do this you will have to do new import in app.module.ts
import {RouterModule} from '#angular/router'
Routermodule has special method forRoot() which registers our routes .
In our case we will have to write this piece of code in
imports :[
RouterModule.forRoot(appRoutes)
]
Our routes are now registered and angular knows our routes now.
Step 5 : Where to display the route content i.e the html content of you route page.
For this angular has directive .
We need to include where we want to load our content i.e in the html.
<a router-outlet="/communication-route"></a>
Navigating to routes :
angular gives a directive for this routerLink
so if we want to navigate to users component , you can give this in your html element:
routerLink="/communication-route"
I hope i was able to explain how this works.
Your code should be as follows
export const ComRoute: Routes = [
{
path: 'communication-route',
children: [
{ path: 'communication', component: communicationComponent },
{ path: ':child1', component: child1Component },
{ path: ':child1/field', component: child1Component}
]
}
];
First of all, states are not an official AngularJS concept. They come from ui-router, which began life as an alternate to the simplistic built in router.
Eventually, ui-router became the de facto standard for routing in AngularJS while the official ng-route module was extracted into a separate, optional library by the Angular team.
ui-router, is complex but exceptional and has earned what is in my view well deserved popularity and success. This success has led to its expansion to support additional platforms enabling the same powerful state based structure in applications written for frameworks such as React.
It is now available for Angular (formerly known as Angular 2).
You can read the documentation and see how to get started on https://ui-router.github.io/ng2
Here is a snippet from the src/app/app.states.ts module of the official example repository
export const loginState = {
parent: 'app',
name: 'login',
url: '/login',
component: LoginComponent,
resolve: [
{ token: 'returnTo', deps: [Transition], resolveFn: returnTo },
]
};
As we can see, there are compatible concepts available, including what looks like a nice evolution of the resolves API which allows function oriented injection which was generally simpler than class based injection in ui-router with AngularJS.
Note, I have not used it in an Angular project.
I've started to write a new angular 2 project and I found that I installed 2 angular router:
"#angular/router": "2.0.0-rc.1",
"#angular/router-deprecated": "2.0.0-rc.1",
I didn't find in the angular site how to use the new router. For example, what component do I need to import.
So my questions are:
Should I use the router-deprecated?
Is there any good doc for how to use the new router?
Here is how to use the Angular 2 Router (RC1), compared to the beta (deprecated) one:
Routes replaces RouteConfig.
Inside your config there is a new syntax:
{path: '/path', component: MyPathComponent}
instead of:
{path:'/path', name: 'MyPath', component: MyPathComponent}
Using routerLink is now like that:
<a [routerLink]="['/path/2']">Click to navigate</a>
Instead of:
<a [routerLink]="['MyPath', 'Detail', {id:2}]">Shark Crisis</a>
Also there is no RouteParams anymore, instead you get the params using
the router lifecycle hooks: CanActivate, OnActivate, and
CanDeactivate.
If you used params inside ngOnInit, you can do that like this now:
routerOnActivate(curr: RouteSegment): void {
curr.getParam('id');
}
You will end up having something like this:
import {ROUTER_DIRECTIVES, Router, Routes} from "#angular/router";
#Injectable()
#Component({
selector: "my-app",
templateUrl: `<a [routerLink]="['/component1']">Click to go to component 1</a>`,
directives: [ROUTER_DIRECTIVES]
})
#Routes([
{path: "/component1", component: Component1},
{path: "/component2", component: Component2}
])
export class AppComponent {
constructor(private _router: Router) {
//If you want to use Router in your component (for navigation etc), you can inject it like this
}
}
Update (9/6/16):
It seems that Angular 2 RC1 Router is being deprecated like the old one.
The new recommendation is to use version 3.0.0-alpha.3 of #angular/router.
Here is more info at the Angular blog:
http://angularjs.blogspot.co.il/2016/06/improvements-coming-for-routing-in.html
Here is an overview of the new router:
http://victorsavkin.com/post/145672529346/angular-router
And here is a working plunker:
http://plnkr.co/edit/ER0tf8fpGHZiuVWB7Q07?p=preview
This helped me get started with the new router:
https://angular.io/docs/ts/latest/guide/router.html
EDIT: Above link is empty for now.. cached version thanks to tylerjgarland: https://web.archive.org/web/20160416143350/https://angular.io/docs/ts/latest/guide/router.html
I also found Misko Hevery's router talk from ng-conf helpful:
https://www.youtube.com/watch?v=d8yAdeshpcw
UPDATE: It appears that the RC1 Router is being abandoned?
https://github.com/angular/angular/issues/9088
Perhaps that is why the docs disappeared rather than being completed...
UPDATE 2: The RC2 Router has now been released:
https://angular.io/docs/ts/latest/guide/router.html
The Component Router is in alpha release. This is the recommended Angular 2 router and supersedes the earlier deprecated beta and v2 routers.
this line in package.json for the new alpha router:
"#angular/router": "3.0.0-alpha.7",
as I found out here: Installing Angular 2 RC2 w/ new component router
Here is another resource you can try (Angular RC.1): https://playcode.org/routing-in-angular-2-rc-1/
And here is the code: https://github.com/jlsuarezs/RoutingExample
I recommend you to use the Angular-CLI to create new routes: https://github.com/angular/angular-cli
Example:
https://github.com/angular/angular-cli#generating-a-route
New Angular 2 router documentation and development work in progress. till that you can use "#angular/router-deprecated".
#AkhileshKumar suggestion is good, try that out i think its all cover basic router usage.
update for RC.1
The new router #angular/router of Angular2 RC.1 is deprecated.
The Angular team is working on providing a new router again.
It was suggested to stay with the old #angular/router-deprecated router until this new new router becomes available
original
The docs for the new router are work in progress. See for example https://github.com/angular/angular.io/pull/1214
The new router has a few issues but in overall is working fine already. If you don't just want to learn about how to use it, I'd wait at least for the next Angular RC version. There are some early adopters that reported a few issues where most are probably easy to fix.
Working nested routeing code for angular2: "#angular/router": "2.0.0-rc.1" i.e. with new router are as follows:
Parent Route:
import {Component} from '#angular/core';
import {Router,Routes,ROUTER_DIRECTIVES} from '#angular/router';
import {Login} from '../login/login';
import {Dashboard} from '../dashboard/dashboard';
import {Admin} from '../admin/admin';
let template = require('./app.html');
#Component({
selector: 'auth-app',
template: template,
directives: [ROUTER_DIRECTIVES],
})
#Routes([
{path: '/login', component: Login},
{path: '/dashboard', component: Dashboard},
{path: '/admin', component: Admin }
])
export class App{
constructor(public router: Router) {
}
}
Child Route
import { Component} from '#angular/core';
import { CORE_DIRECTIVES } from '#angular/common';
import { Router, ROUTER_DIRECTIVES ,Routes} from '#angular/router';
import {AddUsrCat} from './addUsrCat/addUsrCat';
import {AllUsr} from './allUsr/allUsr';
declare var jQuery:JQueryStatic;
let template = require('./admin.html');
#Component({
selector: 'admin',
directives: [CORE_DIRECTIVES, ROUTER_DIRECTIVES],
template: template
})
#Routes([
{path: '/addUsrCat', component: AddUsrCat},
{path: '/allUsr', component: AllUsr},
{path: '*', component: AddUsrCat},
])
export class Admin {
constructor(public router: Router, public http: Http) {
}
}
Clone this project A basic Angular2 ("2.0.0-rc.1") project with authentication (login / logout) works as seed project which uses #angular/router i.e. new route