Reputation: 91
Hi can somebody tell Me what am I doing wrong? I think it's simple error, but I'm new to angular and I can't find it.
EXCEPTION: No provider for String! (SwNavItemCmp -> String)
export interface SwNavItemModel {
name: string;
route: string;
children?: Array<SwNavItemModel>;
}
import {SwNavItemModel} from '../models/sw_nav_item_model';
export const NAV_ITEMS_DATA: Array<SwNavItemModel> = [
{ name: 'Home',
route: '/Home' },
{ name: 'Offer',
route: '/Offer',
children: [
{ name: 'Prices',
route: '/Prices' },
{ name: 'Samples',
route: '/Samples' }
]
},
{ name: 'About',
route: '/About',
children: [
{ name: 'Us',
route: '/Us' },
{ name: 'Projects',
route: '/Projects' },
{ name: 'Skills',
route: '/Skills' }
]
},
{ name: 'Contact',
route: '/Contact' }
];
import {Injectable} from 'angular2/core';
import {NAV_ITEMS_DATA} from '../data/mock_nav_data';
@Injectable()
export class NavService {
getNavData() {
return Promise.resolve(NAV_ITEMS_DATA);
}
}
import {Component, OnInit} from 'angular2/core';
import {
ROUTER_DIRECTIVES
} from 'angular2/router';
import {SwNavItemCmp} from './sw-nav-item/sw_nav_item';
import {SwNavItemModel} from '../../../models/sw_nav_item_model';
import {NavService} from '../../../services/nav_service';
@Component({
selector: 'sw-nav',
templateUrl: './components/shared/sw-nav/sw_nav.html',
styleUrls: ['./components/shared/sw-nav/sw_nav.css'],
providers: [NavService],
directives: [ROUTER_DIRECTIVES, SwNavItemCmp]
})
export class SwNavCmp implements OnInit {
public items: Array<SwNavItemCmp> = [];
constructor(private _navService: NavService) {
}
ngOnInit(): any {
this.getNavData();
}
getNavData() {
this._navService.getNavData().then((navData: Array<SwNavItemModel>) => {
console.log(navData);
console.log(Object.keys(navData));
this.addItems(navData);
});
}
addItem(name: string, route: string, children?: Array<SwNavItemModel>) {
console.log();
console.log('name: ' + name);
console.log('route: ' + route);
console.log('children: ' + children);
if(children) {
let childrenItems: Array<SwNavItemCmp> = [];
console.log('childrenItems: ' + childrenItems);
children.forEach((child) => {
console.log('child: ' + child);
childrenItems.push(new SwNavItemCmp(child.name, child.route, null));
console.log('childrenItems: ' + childrenItems);
});
this.items.push(new SwNavItemCmp(name, route, childrenItems));
console.log('Items: ' + this.items);
} else {
this.items.push(new SwNavItemCmp(name, route, null));
console.log('Items: ' + this.items);
}
}
addItems(itemsArray: Array<SwNavItemModel>) {
console.log('ItemsArray: ' + itemsArray);
itemsArray.forEach((item) => {
console.log('item: ' + item);
item.children ? this.addItem(item.name, item.route, item.children) : this.addItem(item.name, item.route, null);
});
console.log('Items: ' + this.items);
}
}
import {Component, Input} from 'angular2/core';
import {ROUTER_DIRECTIVES} from 'angular2/router';
@Component({
selector: 'sw-nav-item',
templateUrl: './components/shared/sw-nav/sw-nav-item/sw_nav_item.html',
styleUrls: ['./components/shared/sw-nav/sw-nav-item/sw_nav_item.css'],
directives: [ROUTER_DIRECTIVES]
})
export class SwNavItemCmp {
@Input() items: Array<SwNavItemCmp>;
name: string;
route: string;
children: Array<SwNavItemCmp> = [];
constructor(name: string, route: string, children?: Array<SwNavItemCmp>) {
this.name = name;
this.route = route;
this.children = children;
}
}
constructor(name: string, route: string, children?: Array) {...
throw error TS2314: Generic type 'Array<T>' requires 1 type argument(s).
//////////////////////////////////////////////////////////////
Now I have this:
sw_nav.ts
...
export class SwNavCmp implements OnInit {
public items: Array<SwNavItemCmp> = [];
...
}
sw_nav.html
<nav>
<ul class="main-menu">
<li *ngFor="#item of items">
<sw-nav-item [items]="item.children"></sw-nav-item>
</li>
</ul>
</nav>
questions: -Should I pass whole item insted of item.children?
sw_nav_item.ts
import {Component, Input, Inject, Injectable} from 'angular2/core';
import {ROUTER_DIRECTIVES} from 'angular2/router';
@Component({
selector: 'sw-nav-item',
templateUrl: './components/shared/sw-nav/sw-nav-item/sw_nav_item.html',
styleUrls: ['./components/shared/sw-nav/sw-nav-item/sw_nav_item.css'],
directives: [ROUTER_DIRECTIVES]
})
@Injectable()
export class SwNavItemCmp {
@Input() items: Array<SwNavItemCmp>;
name: string;
route: string;
children: Array<SwNavItemCmp>;
constructor(name, route, @Inject(SwNavItemCmp) children: Array<SwNavItemCmp>) {
this.name = name;
this.route = route;
this.children = children;
}
}
questions:
-How should constructor looks like? I think it's invalid.
-How to pass data from input to constructor?
-Should I use Injector.resolveAndCreateChild()
to assing children items?
sw-nav-item.html
???
questions: -How to render it recursive? I want to render all sw-nav-item be itself.
And main questions: -Where should I put var injector = Injector.resolveAndCreate(... provide(...), and how should it looks like? -If I have wrong structure or concept. How to do it right way? I mean recursive components creation and rendreing.
Upvotes: 3
Views: 7353
Reputation: 657348
Update
-How should constructor looks like? I think it's invalid.
The constructor should list the arguments you want to get passed in by Angulars dependency injection (DI). DI can pass values where it has a provider registered in bootstrap (bootstrap(AppComponent, [SomeProvider, ...])
)
-How to pass data from input to constructor? -Should I use Injector.resolveAndCreateChild() to assing children items?
I don't know what you mean by "input" or "children items" here.
You don't need Injector.resolveAndCreateChild()
-How to render it recursive? I want to render all sw-nav-item be itself.
I don't understand the question. How is that related to the constructor?
-Where should I put var injector = Injector.resolveAndCreate(... provide(...),
As mentioned above, you don't need that.
and how should it looks like? -If I have wrong structure or concept. How to do it right way? I mean recursive components creation and rendreing.
You don't need the constructor for this. If you want to pass data from parent to children use binding
<!-- in parent component -->
<some-element [someInput]="someValueFromParent">
@Component({
selector: 'child-component',
})
export class ChildComponent {
@Input() someInput;
constructor() {
// here Angular hasn't yet assigned the `someValueFromParent`
}
ngOnInit() [
// here or in event handlers I can access `someInput` and
// `someValueFromParent` is assigned
}
}
Original
The name
and route
parameters have no providers.
constructor(name: string, route: string, children?: Array<SwNavItemCmp>) {
You can't have parameters in components constructors without telling DI what to pass in.
What's the purpose of these parameters?
Upvotes: 3