ui-router / angular Goto Github PK
View Code? Open in Web Editor NEWUI-Router for Angular: State-based routing for Angular (v2+)
Home Page: https://ui-router.github.io/ng2/
License: MIT License
UI-Router for Angular: State-based routing for Angular (v2+)
Home Page: https://ui-router.github.io/ng2/
License: MIT License
If you have a future state foo.**
and you lazy load a NgModule with states in this order:
foo.bar
foo
foo.baz
The foo.bar
state is "lost".
This is because instead of being queued until foo
is ready, it attaches as a child to the future state foo.**
which is then removed when foo
is registered.
I'm trying to lazy load module Products
app.states.ts:
{
name: 'Products',
url: '/products',
lazyLoad: loadProductsModule
}
lazy.modules.ts:
export function loadProductsModule() {
return loadNgModule(function () {
return System.import('./views/products/products.module')
.then(result => {
return result.ProductsModule;
});
}, ExtraModuleInjector.injector);
}
0.chunk.js getting loaded successfully and System.import is getting resolved with object containing ProductsModule.
But next I'm getting an error: "No NgModule metadata found for '[object Object]"
With native router lazy load of same module works normally.
Could it be because of wrong scoped injector?
loadNgModule Gets the Injector (scoped properly for the destination state)
This one I'm getting from app.component from app module.
If I can't use this one, where should I take correct one? I couldn't find answer in docs.
Thank you.
I noticed the memory is growing after each new transition
I did some debugging and I noticed that all created transition not destroyed due to the usage of it's reference in:
I don't find any way to map url with the hash that come from an implicit oauth redirect,
ex:
http://site.com/#access_token=9a885b89-a9b1-37c9-baa8-a321f83c07d3&token_type=Bearer&expires_in=961&session_state=8ae801dd4a90f6dada6f9af1779096c65b9b15e97661b18750edf134c0b9c7b2.maRdPLUgQesjZQiY-_F71Q
We want to support multilingual urls and hence we want to defer the url to state binding to be done at runtime rather than being performed statically. Imagine we have a sitemap service which retrieves the urls per states e.g.:
{
'en': [
{'module': 'app.home', 'path': ''},
{'module': 'app.about', 'path': '/about'},
],
'sv': [
{'module': 'app.home', 'path': ''},
{'module': 'app.about', 'path': '/om'}
]
}
we want to wire the state app.home
and app.about
to /en
and /en/about
when the language is en
and '/sv' and '/sv/om' when the language is '/sv'.
Looking at UIRouter.forRoot
or UIRouter.forChild
there is a options.config
which could allow us to enable this behaviour which is called from the applyModuleConfig
method:
function applyModuleConfig(uiRouter, injector, options) {
if (options === void 0) { options = {}; }
if (isFunction(options.config)) {
options.config(uiRouter, injector);
}
var states = options.states || [];
states.forEach(function (state) { return uiRouter.stateRegistry.register(state); });
}
What is stopping us from using this hook is the fact that options.config
only takes uiRouter
and injector
as arguments.
Adding options
(module) as a third parameter will allow us to achieve deferred route configuration.
export function applyModuleConfig(uiRouter: UIRouter, injector: Injector, options: StatesModule = {}) {
if (isFunction(options.config)) {
options.config(uiRouter, injector, options);
}
let states = options.states || [];
states.forEach(state => uiRouter.stateRegistry.register(state));
}
As an example of how this would work have a look at the ui-router-multilingual project
To run the project:
npm install
npm start.deving
Open the browser and goto http://localhost:5555/en and hover on the links HOME and ABOUT.
Open the browser and goto http://localhost:5555/sv and hover on the links HOME and ABOUT.
Opening directly the link http://localhost:5555/ will default to english.
To configure multilingual modules we would setup the forChild
and forRoot
we would add the uiRouterConfigureSitemap
config function e.g.
@NgModule({
imports: [CommonModule,
UIRouterModule.forChild({
states:CHILD_STATES,
config: uiRouterConfigureSitemap
})],
declarations: [AboutComponent],
exports: [AboutComponent]
})
export class AboutModule {
}
The config function is simple:
export function uiRouterConfigureSitemap(router: UIRouter, injector: Injector, module: StatesModule) {
let states: ExtNg2StateDeclaration[] = <ExtNg2StateDeclaration[]>module.states;
// Process the states;
let filteredStates: ExtNg2StateDeclaration[] = _.filter(states, (s) => {
return s.future && !s._complete
});
_.map(filteredStates, (s) => {
let sitemapObj:any = _.find(getSitemap(), (sitemap:any) => sitemap.module == s.name);
console.log(`Retrieved ${s.name} from sitemap ${sitemapObj.path}`);
// Set the url from the sitemap object
s.url = sitemapObj.path;
s._complete = true;
});
router.urlService.config.strictMode(false);
}
Note that ui-router-ng2 is committed. node_modules/ui-router-ng2
includes the changes proposed in the Pull Request.
This due to the usage of setTimeout, removing it solve the issue
// app-module.ts
@NgModule({
imports: [
UIRouterModule.forRoot({
states: [
{ name: 'foo.**', url: '/foo', loadChildren: ... }
]
})
],
})
export class AppModule {}
// foo-module.ts
@NgModule({
imports: [
UIRouterModule.forChild({
states: [
{ name: 'foo', url: '/foo', component: ... },
{ name: 'bar', url: '/bar', component: ... }
]
})
],
})
export class FooModule {}
Navigation to /bar
after foo
is loaded produce the following exception:
No component factory found for `BarComponent`.
Resolves fail when using Rollup and multiple classes are included in the build.
In order to reproduce the problem, grab the repo ui-router-ng-resolve-bug and build the project using aot by running
git clone https://github.com/cloudmark/ui-router-ng-resolve-bug
npm install
npm run build.prod.rollup.aot
Serve dist/prod
by running python SimpleHttpServer:
python -m SimpleHTTPServer 8000
Goto http://localhost:8000 and navigate to middle tab Details
. Open the console for the full stack trace, you should see No provider for Transition!.
This works if you compile with aot only (systemjs-builder)
npm run build.prod.aot
or whilst developing by using the dev server
npm run start.deving
Note that compress and mangle have been switched off so that the code is more readable. See tools/tasks/seed/minify.bundles.ts
Looking at the generated code the problem originates from the getDependencies
method in the ResolveContext
class.
ResolveContext.prototype.getDependencies = function(resolvable) {
var _this = this;
var node = this.findNode(resolvable);
var subPath = PathFactory.subPath(this._path, function(x) {
return x === node
}) || this._path;
var availableResolvables = subPath.reduce(function(acc, node) {
return acc.concat(node.resolvables)
}, []).filter(function(res) {
return res !== resolvable
});
var getDependency = function(token) {
var matching = availableResolvables.filter(function(r) {
return r.token === token
});
if (matching.length)
return tail(matching);
var fromInjector = _this.injector().getNative(token);
if (!fromInjector) {
throw new Error("Could not find Dependency Injection token: " + stringify$3(token))
}
return new Resolvable(token,function() {
return fromInjector
}
,[],fromInjector)
};
return resolvable.deps.map(getDependency)
}
specifically the matching
function.
var matching = availableResolvables.filter(function(r) {
return r.token === token
});
Even though the transition
is present, r.token
and token
never match since their reference is not the same.
Looking at the generated code one can in fact find two classes for Transition: Transition$1
and Transition
.
var Transition$1 = function() {
function Transition(fromPath, targetState$$1, router) {
var _this = this;
this._deferred = coreservices_1.services.$q.defer();
this.promise = this._deferred.promise;
this._registeredHooks = {};
this.isActive = function() {
return _this === _this._options.current()
}
;
this.router = router;
this._targetState = targetState$$1;
if (!targetState$$1.valid()) {
throw new Error(targetState$$1.error())
}
this._options = common_1$6.extend({
and
var Transition = function() {
function Transition(fromPath, targetState, router) {
var _this = this;
this._deferred = services.$q.defer();
this.promise = this._deferred.promise;
this._registeredHooks = {};
this.isActive = function() {
return _this === _this._options.current()
}
;
this.router = router;
this._targetState = targetState;
if (!targetState.valid()) {
throw new Error(targetState.error())
}
this._options = extend({
current: val(this)
}, targetState.options());
Since these tokens were create from two different Transition classes the reference match r.token === token
fails and hence the error: No provider for Transition!
.
The Transition
class is present in ui-router-core. UI-router-core and ui-router-ng2 both have two module builds: cjs and esm as follows:
UI-Router-Core:
- cjs build: lib
folder
- esm build: lib-esm
folder
UI-Router-NG2
_bundles/ui-router-ng2.js
lib
folderWhen the angular compile is running aot the lib
folder from ui-router-core is used. You can verify this by running the following command:
node_modules/.bin/ngc -p tsconfig-aot.json
If you open aot/src/client/app/home/home.module.ngfactory.ts
you can see the import
import * as import18 from 'ui-router-core/lib/transition/transition';
I cannot seem to find a way how to instruct tsc
to obey the module
and jsnext:module
properties in package.json.
Rollup on the other hand obeys the module
and jsnext:module
and hence will use lib-esm
folder.
This is exactly why we end up with two Transition
classes in the final build. One is originating from the lib
(cjs) folder and the other is from lib-esm
being used by rollup.
version: 1.0.0-beta.4
For some reason in newly created angular-cli project, if resolver returns promise that resolves asynchronously, second transition to same state appearing without waiting for promise result.
export function twoRouteResolver() {
return new Promise(resolve => {
setTimeout(() => {
console.log('%cchecking', 'color:red;');
console.log('resolving');
resolve();
}, 1000);
});
}
Without timeout second transition does not appear.
Demo:
https://github.com/lexigren/UIRouterResolverProblemDemo
Note: this is the Angular 1.x source for UI-Router version 1.0.
{home}/sub
<base href="/sub/">
to index.html
UIRouterModule.forRoot
and add an otherwise
rule { }
@NgModule({
imports: [
BrowserModule,
UIRouterModule.forRoot({ states: [ helloState, aboutState ], otherwise: { state: 'hello' } })
],
declarations: [ App, Hello, About ],
bootstrap: [ App ]
})
class RootAppModule {}
{home}/
and go to the local app. The hello
state can be successfully redirected, but when I click the about
link, nothing happens (should expect to navigate to about
state).The issue does not occur either when there is no base url or otherwise
rule.
I want to be able to check if a user is authenticated and/or authorized to visit a view state before each transition to a new view/state. The default angular router has a 'canActivate' feature that is run before the app transitions to a new view.
How can I achieve the same using ui-router? I've searched the docs, the codebase here, and the web but have not found anything.
Thanks for your help
When passing an array as search query through the param using the [uiPrams] everything work as expected where the param is returned as array of string. However, passing the search query through the url such as ?param=test1¶m=test2 the app is returning a string (test2) instead of array of string.
Plunker example has 2 link where one is using the uiSref, the other one is using the href
https://plnkr.co/edit/HNeb0egtVUFUt7eNPpfZ?p=preview
I believe the issue is caused by this line in location.ts
loc.search = <any> (() => {
let queryString = splitOnHash(splitOnQuestionMark(locSt.path())[1])[0];
return queryString.split("&").map(kv => splitOnEquals(kv)).reduce(applyPairs, {});
});
The applyPairs function return key, value assumed that keys are unique.
From @artaommahe on January 8, 2017 20:16
uiSref
directives binds 'null'
string to href
on provided null
or empty string ''
state.
current behavior
<!-- template -->
<a [uiSref]="null">smth</a>
<a [uiSref]="''">smth</a>
<!-- result -->
<a href="null">smth</a>
expected no href
attribute (null property value?)
<!-- result -->
<a>smth</a>
It's required for dynamic links when for some cases href
should be empty and link clicks does not trigger any state changes (access rights check e.x.)
Copied from original issue: angular-ui/ui-router#3248
Exception: Call to Node module failed with error: ReferenceError: window is not defined
at Ng2LocationServices.BaseLocationServices
at new Ng2LocationServices
at uiRouterFactory
Has anyone gotten ui-router-ng2 to work with angular-universal.
It appears to have a requirement on the DOM?
The resolve data doesn't supplies component inputs anymore in AoT build since the last version of @angular/cli
as it remove all angular decorators in order to have less bundle size.
I propose to introduce custom decorator for resolve data:
@Component({ ... })
export class App {
@Resolve() foo;
}
Environment:
if use resolve, exp:
resolve: [ { token: 'people', deps: [PeopleService], resolveFn: (peopleSvc) => peopleSvc.getAllPeople() } ]
will get errors
Uncaught TypeError: Cannot convert undefined or null to object at Function.getPrototypeOf (<anonymous>) at getParentCtor (http://localhost:8080/vendor.dll.js:60384:47) at ReflectionCapabilities.annotations (http://localhost:8080/vendor.dll.js:60241:43) at Reflector.annotations (http://localhost:8080/vendor.dll.js:60448:44) at DirectiveResolver.isDirective (http://localhost:8080/vendor.dll.js:17086:61) at http://localhost:8080/vendor.dll.js:18710:42 at Array.forEach (native) at CompileMetadataResolver._getEntryComponentsFromProvider (http://localhost:8080/vendor.dll.js:18709:30) at http://localhost:8080/vendor.dll.js:18682:83 at Array.forEach (native) at CompileMetadataResolver._getProvidersMetadata (http://localhost:8080/vendor.dll.js:18652:19) at http://localhost:8080/vendor.dll.js:18259:63 at Array.forEach (native) at CompileMetadataResolver.getNgModuleMetadata (http://localhost:8080/vendor.dll.js:18250:49) at CompileMetadataResolver.getNgModuleSummary (http://localhost:8080/vendor.dll.js:18192:52) at http://localhost:8080/vendor.dll.js:18263:72 at Array.forEach (native) at CompileMetadataResolver.getNgModuleMetadata (http://localhost:8080/vendor.dll.js:18250:49) at JitCompiler._loadModules (http://localhost:8080/vendor.dll.js:52289:64) at JitCompiler._compileModuleAndComponents (http://localhost:8080/vendor.dll.js:52249:52) at JitCompiler.compileModuleAsync (http://localhost:8080/vendor.dll.js:52215:21) at PlatformRef_._bootstrapModuleWithZone (http://localhost:8080/vendor.dll.js:40098:25) at PlatformRef_.bootstrapModule (http://localhost:8080/vendor.dll.js:40073:21) at HTMLDocument.main (http://localhost:8080/main.bundle.js:2918:10) at ZoneDelegate.invokeTask (http://localhost:8080/polyfills.dll.js:4195:35) at Zone.runTask (http://localhost:8080/polyfills.dll.js:4071:47) at HTMLDocument.ZoneTask.invoke (http://localhost:8080/polyfills.dll.js:4265:33)
Pls help !!!
See original bug report: angular-ui/ui-router#3227
If you use otherwise: '/'
, the otherwise function kicks in a sets the url. However, the url is not sync'd so the proper state is never activated.
HI!
How to organize personal profile url with ui-router ?
Like:
http://github.com.com/christhielen
<a target="_blank"
[uiSref]="'someState">
</a>
Will open state in current tab instead of new one.
From @christopherthielen on October 13, 2016 17:43
We're currently importing from rxjs/Rx
like:
import { Observable } from "rxjs/Rx";
import { ReplaySubject } from "rxjs/Rx";
import {Subscription, ReplaySubject} from "rxjs/Rx";
we might be able to do deep imports instead, so people don't have to load the entire rxjs/Rx
package.
Need some research on the proper approach to allow users to either load the entire rxjs as a bundle, or build their own using webpack, etc.
Copied from original issue: angular-ui/ui-router#3087
We need to add router.urlMatcherFactory.$get()
right around here to auto-flush the param type registration queue.
HI! Guys, Thank you for your amazing work. In my company we are building a large app with angular 1 + ui-router, but we've decided to upgrade to angular 2. We already bootstrapped the angular 1 app, everything is running as supposed, but we're facing some troubles to route ng2 components with ui-router for ng2. Can someone give the light?
This is my bootstrap
* Create our upgradeAdapter
*/
const upgradeAdapter: UpgradeAdapter = new UpgradeAdapter(
forwardRef(() => WiseitAppModule));
/*
* Expose our ng1 content to ng2
*/
uiRouterNgUpgrade.setUpgradeAdapter(upgradeAdapter);
upgradeAdapter.upgradeNg1Provider('$state');
@NgModule({
declarations: [
HelloWorldComponent
],
imports: [
CommonModule,
BrowserModule,
FormsModule,
Ng1ToNg2Module,
UIRouterModule.forRoot({ states: [helloState], useHash: true,})
],
providers: []
})
export class WiseitAppModule {
}
/*
* Bootstrap the App
*/
upgradeAdapter.bootstrap(document.documentElement, ['wiseit'], {strictDi: false});
This is my test route
export const helloState = {
name: 'hello',
url: '/hello-world',
component: HelloWorldComponent
};
From @kolkov on September 18, 2016 0:38
Compiler errors:
D:\Go\src\inframe\static2>node_modules/.bin/ngc -p tsconfig-aot.json
Error: Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol PublicModule in
D:/Go/src/inframe/static2/app/public/public.module.ts, resolving symbol PublicModule in D:/Go/src/inframe/static2/app/public/public.module.ts
at simplifyInContext (D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\src\static_reflector.js:469:23)
at StaticReflector.simplify (D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\src\static_reflector.js:472:22)
at StaticReflector.annotations (D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\src\static_reflector.js:61:36)
at _loop_1 (D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\src\codegen.js:53:54)
at CodeGenerator.readFileMetadata (D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\src\codegen.js:66:13)
at D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\src\codegen.js:100:74
at Array.map (native)
at CodeGenerator.codegen (D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\src\codegen.js:100:35)
at codegen (D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\src\main.js:7:81)
at Object.main (D:\Go\src\inframe\static2\node_modules\@angular\compiler-cli\node_modules\@angular\tsc-wrapped\src\main.js:30:16)
Compilation failed
PublicModule:
var publicState = { name: 'public', url: '/public', component: PublicComponent };
var homeState = { name: 'public.home', url: '/home', component: PublicHomeComponent };
var aboutState = { name: 'public.about', url: '/about', component: PublicAboutComponent };
var userState = { name: 'public.user', url: '/user', component: PublicUserComponent };
var signupState = { name: 'public.user.signup', url: '/signup', component: PublicSignupComponent };
var loginState = { name: 'public.user.login', url: '/login', component: PublicLoginComponent };
@NgModule({
imports: [
CommonModule,
NgbModule,
FormsModule,
UIRouterModule.forChild({
states: [homeState, publicState, aboutState, userState, signupState, loginState]
}),
],
declarations: [
PublicComponent,
PublicAboutComponent,
PublicHomeComponent,
NgbdCarouselBasic,
PublicLoginComponent,
PublicUserComponent,
PublicSignupComponent
],
providers:[]
})
export class PublicModule { }
Copied from original issue: angular-ui/ui-router#3012
Hi guys,
Playing with HMR with Angular-CLI - following basically this: https://medium.com/@beeman/tutorial-enable-hrm-in-angular-cli-apps-1b0d13b80130#
But I'm seeing the UI-Route refreshing the entire component. Has anyone had a go with HMR, Angular2 and UI-Router?
The tutorial ends with suggesting that you can use .person instead of people.person for relative addressing. I could not get this to work however (it works otherwise). Is that a bug? Or am I just missing something?
Hi ! some problems with my States.
In my @NgModule > providers, I add a service named "myService", beacause I want a unique instance of my service in the whole App. In my components I can inject my services which share the same instance of the service.
So now, in my State declaration, I add a resolvable :
{
name: 'myState',
url: '/user/:userId',
component: ViewUserComponent,
resolve: [
new Resolvable('user', (http, trans, uService) => {
return new Promise((resolve, reject) => {
let id = trans.params().userId;
http
.get('myUrl ' + id)
.subscribe((res: Response) => {
let u = new User(res.json());
new uService.add(u);
resolve(u);
}, reject);
});
}, [Http, Transition, userService])
]
}
In my userService constructor I put a console.log, and I can see multiple "construct UserService". Xhy UIRouter don't take the app instance of the service? How can I force him to use this one ?
11 12 2016 01:15:15.844:ERROR [config]: File D:\!Projects\TypeScript\ui-router\ui-router-ng2\config\karma.ng2.js does not exist!
From @kolkov on September 8, 2016 11:10
<li class="nav-item btn-group" ngbDropdown>
<a class="dropdown-toggle nav-link" role="button" ngbDropdownToggle>Profile <span class="tag tag-pill tag-default">44</span></a>
<div class="dropdown-menu">
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.messages" uiSrefActive="active">Messages <span class="tag tag-pill tag-default">42</span></a>
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.polling" uiSrefActive="active">Polling <span class="tag tag-pill tag-default">2</span></a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Advanced</div>
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile" uiSrefActive="active">Profile</a>
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.settings" uiSrefActive="active">Settings</a>
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.password" uiSrefActive="active">ChangePassword</a>
</div>
</li>
When we click on private.profile.password
:
private.profile
=> activeprivate.profile.password
=> activebut in this case if clicked on private.profile.password
:
<li class="nav-item btn-group" ngbDropdown>
<a class="dropdown-toggle nav-link" role="button" uiSref="private.profile" uiSrefActive="active" ngbDropdownToggle>Profile <span class="tag tag-pill tag-default">44</span></a>
<div class="dropdown-menu">
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.messages" uiSrefActive="active">Messages <span class="tag tag-pill tag-default">42</span></a>
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.polling" uiSrefActive="active">Polling <span class="tag tag-pill tag-default">2</span></a>
<div class="dropdown-divider"></div>
<div class="dropdown-header">Advanced</div>
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.person" uiSrefActive="active">PersonProfile</a>
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.settings" uiSrefActive="active">Settings</a>
<a class="dropdown-item" (click)='isCollapsed = true' uiSref="private.profile.password" uiSrefActive="active">ChangePassword</a>
</div>
</li>
only private.profile
is active, but private.profile.password
is not active. Is this correct?
Copied from original issue: angular-ui/ui-router#2980
This is a duplicate issue of angular-ui/ui-router#3326, as I wasn't sure where the appropriate place to file it was. Upon upgrading my app to [email protected]
I started receiving a duplicate state declaration error in the following situation.
If I have two modules:
//app/foo/foo.module.ts
import { NgModule } from '@angular/core';
import { UIRouterModule } from 'ui-router-ng2';
import FooComponent from './foo.component';
@NgModule({
imports: [
UIRouterModule.forChild({ states: [
{
name: 'foo',
url: '/foo',
component: FooComponent
}
]),
],
declarations: [],
exports: [],
providers: [],
})
export default class FooModule { }
//app/bar/bar.module.ts
import { NgModule } from '@angular/core';
import { UIRouterModule } from 'ui-router-ng2';
import FooModule from '../foo/foo.module';
import BarComponent from './bar.component';
@NgModule({
imports: [
UIRouterModule.forChild({ states: [
{
name: 'bar',
url: '/bar',
component: BarComponent
}
]),
FooModule,
],
declarations: [],
exports: [],
providers: [],
})
export default class BarModule { }
In this case I receive a runtime error stating State 'foo' is already defined
, as a result of adding FooModule
to the list of imports in BarModule
. I'm not sure if this is intended behavior, however this is not how the router behaves in [email protected]
Hi! How to get queryParams in our ui-router-ng2 like in native router?
ngOnInit() {
this.route.queryParams
.map((params: Params) => params['code'])
.flatMap((code: string) => this.authService.exchange(code))
.map((success: boolean) => success ? this.succeed() : this.fail())
.subscribe();
}
From this request for example:
http://mydomain.com/facebook?code=AQBDRKsrmT4iyYZ1bOOEpncXNcor0584NW8MYLj-VaEyGhBoQ6Iup8PHWjPFK7V2PUaZ7zwreyEh9F8tpENJQLbpKqTENVOwEP2Xetddj7h-rLHc_3wzYaefbP0VetK29NknI1UDtQiOoCvdR7-lQhUI5f24FS5iVyr4azTH4ef5OXhFmNfsNHn23Jo2ngkj3XrEgDbrPs8L61d33U0Vejy02PmVElF6c42_OAsB4P5XCmYqC9yYWBXabQiVPSr1Zn4mC7rnqoDOm0T40nDLH4IK61QgeoSkmQqkpC0ze1S7qc6xAyG39PPqvFxgCnEOR1fBLRQwFyFa57mltIEUR5-J&state=thisshouldberandom#_=_
This plunker shows how to respond to changes in uiSref
status using the uiSrefStatus
events.
https://plnkr.co/edit/PEWdPiLCYegixwdGAdb5?p=preview
@Component({
selector: 'my-app',
directives: [UIROUTER_DIRECTIVES],
template: `
<div class="nav">
<a uiSref="hello" uiSrefActive="active" (uiSrefStatus)="updated('hello', $event)">Hello</a>
<a uiSref="about" uiSrefActive="active" (uiSrefStatus)="updated('about', $event)">About</a>
<a uiSref="people" uiSrefActive="active" (uiSrefStatus)="updated('people', $event)">People</a>
</div>
<ui-view></ui-view>
`})
export class App {
active = {
hello: false,
about: false,
people: false,
}
updated(state, event) {
console.log(state, event);
this.active[state] = event.active;
console.log("active states", this.active);
}
}
It would be nice not to have to bind the sref target manually, i.e., updated($event)
instead of updated('hello', $event)
.
We can add the sref target to the event so it can be used in a handler.
When we declare a state with lazyLoad it end up getting the module even if we stop / supersed the transition.
Shouldn't the lazyLoad wait for the onbefore being resolved?
This is a simple example that i use with a login state and a top state protected by a transitionHook that redirect to the login if we aren't authenticated.
let login = {name: 'login', url: '/login', component: AuthComponent};
let top = {name: 'top', url: '/', component: AuthComponent};
let user = {name: 'top.user.**', url: 'user', loadChildren: () => System.import('./app/user.module.ts')};
export function requireAuthentication(transition: Transition) {
let $state = transition.router.stateService;
return $state.target('login');
}
export function uiRouterConfigFn(router: UIRouter) {
// Use ui-router-visualizer to show the states as a tree
// and transitions as a timeline
visualizer(router);
let authCriteria = {to: 'top.**'};
router.transitionService.onBefore(authCriteria, requireAuthentication);
}
@NgModule({
imports: [
BrowserModule,
UIRouterModule.forRoot({
states: [login, top,user],
config: uiRouterConfigFn
}),
],
declarations: [
AppComponent,
AuthComponent
],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule { }
let user = { name: 'top.user', url: 'user', component: UserComponent};
@NgModule({
imports: [
UIRouterModule.forChild({
states: [user]
})
],
declarations: [
UserComponent
]
})
export default class UserModule {}
When you go to the future state you end up getting rejected to the login, but the module is still loaded. And you get an error for the transition being superseded by a different transition.
This error doesn't happen if we aren't using lazyLoading ( Or is silenced)
You can see the example on this plunker :https://plnkr.co/edit/RR2tABzqH26p75gPbnuE
If you don't explicitly import all the RxJS operators that UI-Router requires (primarily for the UISref directive) they seem to get tree-shaked away when running in AoT (--aot
) and/or production build (--prod
).
UI-Router imports the operators in the index file:
import "rxjs/Observable";
import "rxjs/ReplaySubject";
import "rxjs/BehaviorSubject";
import "rxjs/Subscription";
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/combineLatest';
import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/concat';
import 'rxjs/add/operator/map';
but they seem to get stripped away (likely due to webpack tree shaking) and cause an exception at runtime
TypeError: this._globals.start$.switchMap is not a function
at UISrefStatus.ngAfterContentInit (vendor.bundle.js:13026)
at View_ContactListComponent1.webpackJsonp.762.View_ContactListComponent1.detectChangesInternal (1.chunk.js:1074)
at View_ContactListComponent1.AppView.detectChanges (vendor.bundle.js:7364)
at ViewContainer.detectChangesInNestedViews (vendor.bundle.js:10602)
at View_ContactListComponent0.webpackJsonp.762.View_ContactListComponent0.detectChangesInternal (1.chunk.js:1188)
at View_ContactListComponent0.AppView.detectChanges (vendor.bundle.js:7364)
at View_ContactListComponent0.AppView.internalDetectChanges (vendor.bundle.js:7349)
at View_ContactsComponent0.webpackJsonp.764.View_ContactsComponent0.detectChangesInternal (1.chunk.js:1645)
at View_ContactsComponent0.AppView.detectChanges (vendor.bundle.js:7364)
at View_ContactsComponent0.AppView.internalDetectChanges (vendor.bundle.js:7349)
at View_ContactsComponent_Host0.webpackJsonp.764.View_ContactsComponent_Host0.detectChangesInternal (1.chunk.js:1573)
at View_ContactsComponent_Host0.AppView.detectChanges (vendor.bundle.js:7364)
at ViewRef_.detectChanges (vendor.bundle.js:36485)
at UIView.applyInputBindings (vendor.bundle.js:8271)
at UIView.applyUpdatedConfig (vendor.bundle.js:8229)
I'm not sure what best practice is regarding these imports, but it seems to work if the imports are moved into each file that requires the operator.
Related to: #28
10% building modules 2/2 modules 0 active(node:10804) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol AppModule in C:/angular2/SOFTWARE_MANAGEMENT/src/app/app.module.ts, resolving symbol AppModule in C:/angular2/SOFTWARE_MANAGEMENT/src/app/app.module.ts
20% building modules 87/87 modules 0 active
When I remove the references to UIRouterModule, then ng serve and then add them again, everything works just fine. So somewhere the type registration fails to happen at the right time? I'm fairly new at typescript and angular 2, so it may be a noobish error, but can't find what's causing it.
Should you want to dive into the sourcecode, it's public, here: https://github.com/niwrA/Software-Management-Angular2-Client
From @Jordan-Hall on November 14, 2016 13:52
Does anyone know an example of how you get ui-router-ng2 to lazy load modules when using webpack. I've tried everything
Copied from original issue: angular-ui/ui-router#3151
angular-ui/ui-router#3063
This issue moved from angular-ui/ui-router#3065
Named views in ng2 currently look like this:
views: {
foo: { component: FooCompoent }
}
We should also support the same shorthand as we do in ng1:
views: {
foo: FooCompoent
}
This issue moved from: angular-ui/ui-router#3066
When returning an errored observable from a resolve factory the state transition never happens (state home.observable-that-throws). Furthermore, the items that are emitted after the first item don't seem to be passed on to the stream that is resolved (home.observable).
Plunker: http://plnkr.co/edit/x2mTrhH3RQuNV4fcXSrO?p=preview
Expected: http://plnkr.co/edit/MXMAAWLDD6jGUz99SDlG?p=preview
After upgrading from 1.0.0-beta.3
to 1.0.0-beta.4
, the application breaks and I have this error in console:
Uncaught TypeError: d.UIRouterRx is not a constructor
Note: I thought UIRouterRx was an optional plugin, but then I found it imported and configured in src/providers.ts
and now I'm confused.
include lazy loading
bindings:
is used to map resolve data to component inputs. It is supposed to work both on a view declaration and on a state declaration, however it only works on a view declaration.
This currently works:
const state = {
name: 'foo',
views: {
$default: {
component: FooComponent,
bindings: { fooData: 'fooResolve' },
}
},
resolve: [ { token: 'fooResolve', resolveFn: fooResolveFn } ],
}
This does not currently work in beta.4:
const state = {
name: 'foo',
component: FooComponent,
bindings: { fooData: 'fooResolve' },
resolve: [ { token: 'fooResolve', resolveFn: fooResolveFn } ],
}
related to: #45
related to #36
If a state has explicitly defined mappings, we currently only apply those mappings if we find a matching @Input()
or inputs: []
metadata. Because decorators are now being stripped for AoT compile, there is no longer any way to be certain that the property exists on the component or not.
For now, we should always set the property on the component (if an explicit binding is made), even if the metadata is not found.
var state = {
resolve: [ { token: 'fooData', resolveFn: getFoo } ],
component: FooComponent,
bindings: { fooData: 'fooData' },
}
cc @aitboudad
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.