Giter VIP home page Giter VIP logo

angular's Introduction

UI-Router for Angular  Build Status

@uirouter/angular: State based routing for Angular (v2+)


Tutorials | API Docs | Guides | Sample App | Report an Issue | Contribute | Help!


@uirouter/angular is a client-side Single Page Application routing framework for Angular.

Routing frameworks for SPAs update the browser's URL as the user navigates through the app. Conversely, this allows changes to the browser's URL to drive navigation through the app, thus allowing the user to create a bookmark to a location deep within the SPA.

UI-Router applications are modeled as a hierarchical tree of states. UI-Router provides a state machine to manage the transitions between those application states in a transaction-like manner.

Get Started

Reporting issues and Contributing

Please read our Contributor guidelines before reporting an issue or creating a pull request.

angular's People

Contributors

0x-r4bbit avatar adambabik avatar aitboudad avatar amcdnl avatar christopherthielen avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar dependencies-bot avatar eddiemonge avatar fpipita avatar gigadude avatar greenkeeper[bot] avatar greenkeeperio-bot avatar hshn avatar jeme avatar ksperling avatar nateabele avatar oliverguenther avatar patrickjs avatar peterdavehello avatar philbrown avatar proloser avatar sbezkostnyi avatar scooper91 avatar timkindberg avatar uirouterbot avatar wawyed avatar wesleycho avatar ysbaddaden avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular's Issues

Lazy loading states in wrong order can cause states to be lost.

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.

new instance of services

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 ?

Uncaught TypeError: d.UIRouterRx is not a constructor

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.

Transition Ignored?

Hi! What may causing this problem on prod server?

image
one difference base href and port...
prod:
image
and dev:
image

Parameters implicitly have an 'any' type

Hi,

I just got some errors when I imported { UIRouterModule } from 'ui-router-ng2'(please see the attachment).
ui-router-error

If anyone knows what happened, please help me.

Thanks,

ng2: uiSrefActive error

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:

  1. private.profile => active
  2. private.profile.password => active

image

image

but 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>

image

image

only private.profile is active, but private.profile.password is not active. Is this correct?

Copied from original issue: angular-ui/ui-router#2980

Get error when using "resolve"

Environment:

  • angular 2.4.3
  • ui-router: 1.0.0-beta.4

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 !!!

test error

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!

README.md typo

Note: this is the Angular 1.x source for UI-Router version 1.0.

Angular Universal w /Dotnet core reports window not found

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?

State 'foo' is already defined - [email protected]

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]

[@angular/cli] input decorator is removed when using the AoT build

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;
}

Request param from the url query string return string instead of array for param with multiple value

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&param=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.

Failed to navigate to a different state when defined with base URL and `otherwise` path

How to reproduce

  • Save a local copy of the official helloworld app
  • Move all files to a subfolder, e.g., {home}/sub
  • add <base href="/sub/"> to index.html
  • turn off useHash for 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 {}
  • serve the app from {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.

"No NgModule metadata found" for lazy loaded module

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.

Rejecting a transition that lazyLoad a module still load the module

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

Hybrid app (ng1+ng2)

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
};

Empty links by ng2 `uiSref` directive

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

ng2: deep rxjs imports?

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

Is ui-router AoT compatible?

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

Relative child-routing

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?

Specifying bindings: does not work unless inside a views: block

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

[Lazyload] newly loaded states use the wrong Injector

// 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`.

How to get queryParams

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#_=_

Lifecycle Callbacks

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

[Resolve] async ResolvePolicy "RXWAIT" does not behave as expected

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

Build / typescript type registration issue with Angular CLI

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

Explicitly declared component bindings should always be mapped

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

Rollup Issue - Resolves fail when using Rollup, multiple extra classes are included in the build

Resolves fail when using Rollup and multiple classes are included in the build.

How to Reproduce

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

Investigation

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.

screen shot 2017-02-19 at 16 25 33

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!.

So how are these two transition classes created?

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

  • cjs build: _bundles/ui-router-ng2.js
  • esm build: lib folder

When 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.

RxJS operators used by ui-router are missing when built using angular-cli AoT

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

Double transition with async route resolver

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

RFC: Add State Module to options.config to enable multilingual routes

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));
}

Example

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.

  • HOME should point to /en/
  • ABOUT should point to /en/about

Open the browser and goto http://localhost:5555/sv and hover on the links HOME and ABOUT.

  • HOME should point to /sv/
  • ABOUT should point to /sv/om

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.

Feat: emit the state/params in `uiSrefStatus` events

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.