【问题标题】:Angular2 - asp.core - Fails to bind directives when routing to specific urlAngular2 - asp.core - 路由到特定网址时无法绑定指令
【发布时间】:2017-08-30 14:11:04
【问题描述】:

我在这方面花了很多时间,并且即将挥舞白旗。

我的应用在从 index.html 运行时运行良好,我延迟加载了一个使用绑定来应用样式以进行测试的功能。

但是,如果我直接转到 url,我会得到异常

“调用节点模块失败并出现错误:错误:未捕获(承诺中): 类型错误:无法设置未定义的属性“填充”。

让事情变得更难的是,highlight 指令工作正常,它只是我的标签指令不绑定。如果我从我的 html 中删除标签属性,则页面加载正常。我真的很难找到导致此问题的问题。

应用模块

import { NgModule } from '@angular/core';
import { UniversalModule } from 'angular2-universal';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './components/app/app.component'
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { HomeComponent } from './components/home/home.component';
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
import { CounterComponent } from './components/counter/counter.component';
import { HeroDetailComponent } from './components/hero/hero-detail.component';
import { HeroListComponent } from './components/hero/hero-list.component';
import { HeroService } from './components/hero/hero.service';
import { HeroDashboardComponent } from './components/hero/hero-dashboard.component';
import { HeroMainComponent } from './components/hero/hero-main.component';
import { HeroFormComponent } from './components/form/hero-form.component';

import { ReactiveFormModule } from './components/form-reactive/form-reactive.module';

import { CoreModule } from './components/core/core.module';

import { AppRoutingModule } from './app.routes'

@NgModule({
    bootstrap: [AppComponent],
    imports: [
        UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
        HttpModule,
        FormsModule,
        AppRoutingModule,
        ReactiveFormsModule,
        CoreModule,
        ReactiveFormModule
    ],
    declarations: [
        AppComponent,
        NavMenuComponent,
        CounterComponent,
        FetchDataComponent,
        HomeComponent, 
        HeroDetailComponent,
        HeroListComponent,
        HeroDashboardComponent,
        HeroMainComponent,
        HeroFormComponent
    ],
    providers: [HeroService]
})

export class AppModule {}

app.routes.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
import { CounterComponent } from './components/counter/counter.component';
import { HeroDetailComponent } from './components/hero/hero-detail.component';
import { HeroListComponent } from './components/hero/hero-list.component';
import { HeroDashboardComponent } from './components/hero/hero-dashboard.component';
import { HeroMainComponent } from './components/hero/hero-main.component';
import { HeroFormComponent } from './components/form/hero-form.component';    

export const routes: Routes = [
    { path: '', redirectTo: 'hero/dashboard', pathMatch: 'full' },
    { path: 'home', component: HomeComponent },
    { path: 'counter', component: CounterComponent },
    { path: 'fetch-data', component: FetchDataComponent },
    {
        path: 'hero', component: HeroMainComponent, children:
        [
            { path: '', component: HeroListComponent }, // url: hero/
            { path: 'dashboard', component: HeroDashboardComponent },
            { path: 'detail/:id', component: HeroDetailComponent },
        ]
    },
    { path: 'form', component: HeroFormComponent },
    { path: 'form-reactive', loadChildren: () => { return Promise.resolve(require('./components/form-reactive/form-reactive.module')['ReactiveFormModule']) }},
    { path: 'core-tracking', loadChildren: () => { return Promise.resolve(require('./components/core/core.module')['CoreModule']); } },
    { path: '**', redirectTo: 'home' }
]

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class AppRoutingModule { }

核心路由.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CoreTrackingMainComponent } from './coreTrackingMain.component';

@NgModule({
    imports: [RouterModule.forChild([
        { path: '', component: CoreTrackingMainComponent }
    ])],
    exports: [RouterModule]
})
export class ContactRoutingModule { }

core.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import { ContactRoutingModule } from './core-routing.module';

import { CoreTrackingMainComponent } from './coreTrackingMain.component';
import { CoreTrackingCriteriaComponent } from './coreTrackingCriteria.component';
import { CriteriaLabelDirective } from './coreCriteriaLabel.directive';
import { HighlightDirective } from './coreCriteriaHighlight.directive';


@NgModule({
    imports: [CommonModule, ReactiveFormsModule, ContactRoutingModule],
    declarations: [
        CoreTrackingMainComponent,
        CoreTrackingCriteriaComponent,
        CriteriaLabelDirective,
        HighlightDirective,
    ],
    exports: [
        CoreTrackingMainComponent,
        CoreTrackingCriteriaComponent
    ]
})
export class CoreModule { }

coreCriteriaLabel.directive.ts

    import { Directive, ElementRef } from '@angular/core';

    @Directive({ selector: '[myLabel]' })

    export class CriteriaLabelDirective {
        constructor(el: ElementRef) {
            el.nativeElement.style.padding = '6px 0';
}
        }

coreCriteriaHighlight.directive.ts

import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({ selector: '[myHighlight]' })

export class HighlightDirective {
    @Input('myHighlight') highlightColor: string;
    constructor(private el: ElementRef) { }
    @HostListener('mouseenter') onMouseEnter() {
        this.highlight(this.highlightColor || 'red');
    }
    @HostListener('mouseleave') onMouseLeave() {
        this.highlight(null);
    }
    private highlight(color: string) {
        this.el.nativeElement.style.backgroundColor = color;
    }
}

coreTrackingCriteria.component.html

<h2>Core Tracking Criteria</h2>
<div class="criteria-container col-xs-12">
    <form [formGroup]="trackingForm" novalidate>
        <div class="form-group">
            <div class="col-md-6">
                <label [myHighlight]="color" class="control-label col-xs-4">Reader Organization</label>
                <div class="col-xs-8">
                    <input class="form-control" formControlName="readerOrg">
                </div>
            </div>
            <div class="col-md-6">
                <label [myLabel] class="control-label col-xs-4">Location</label>
                <div class="col-xs-8">
                    <input class="form-control" formControlName="location">
                </div>
            </div>
        </div>
    </form>
</div>

coreTrackingCriteria.component.ts

import { Component } from '@angular/core';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
    selector: 'core-criteria',
    templateUrl: './coreTrackingCriteria.component.html',
    styleUrls: ['./coreTrackingCriteria.component.css']
})
export class CoreTrackingCriteriaComponent {

    constructor(private fb: FormBuilder) {
        this.createForm();
    }

    color: string = 'blue';

    trackingForm: FormGroup;

    createForm() {
        this.trackingForm = this.fb.group({
            readerOrg: ['', Validators.required],
            location: ['', Validators.required],
        });
    }

}

更新

实现 ngOnInit() 而不是在指令中使用构造函数。仍然导致同样的问题

coreCriteriaLabel.directive.ts

import { Directive, ElementRef, Input, OnInit } from '@angular/core';

@Directive({ selector: '[myLabel]' })

export class CriteriaLabelDirective implements OnInit {

    constructor(private el: ElementRef) {
    }

    ngOnInit() {
        this.el.nativeElement.style.padding = '6px 0';
    }
}

【问题讨论】:

  • 你能显示使用该指令的html吗?
  • myLabel 在哪里以及如何使用?您是否尝试过将el.nativeElement.style.padding = '6px 0'; 移动到ngOnInit()ngAfterContentInit()(虽然没有必要)?
  • 更新了我的帖子,@günter-zöchbauer 我应该将 ngOnInit() 应用于我的指令,我认为这些钩子通常应用于组件
  • 组件是一个带有视图的指令。指令可以有输入,因此ngOnChange()ngOnInit() 也是指令所需的生命周期方法。指令与具有模板&lt;ng-content&gt;&lt;/ng-content&gt; 的组件非常相似,因此ngAfterContentInit() 也在工作AFAIK,我也很确定ngAfterViewInit() 被调用,即使指令没有视图。因此,我认为这绝对值得一试。
  • 更新了我的帖子,添加 ngOnInit() 后没有引起同样的问题。刚刚删除了我的 Highlight Directive 中的 @HostListener 接口,我遇到了同样的错误。

标签: angular angular2-routing angular2-directives


【解决方案1】:

好的,我终于得到了我的指令。

  1. 我使用了 Renderer 类而不是直接附加到 元素原生元素。
  2. 我还需要包含@Input 应用程序正确编译的装饰器。

    对此行为的原因的任何解释将不胜感激。

    import { Directive, Renderer, ElementRef, Input,  } from '@angular/core';
    @Directive({ selector: '[myLabel]' })
    
    export class CriteriaLabelDirective  {
        @Input('myLabel') myLabel;
        constructor(private renderer: Renderer, private el: ElementRef) {
                this.renderer.setElementStyle(this.el.nativeElement, 'padding', '6px 0');
        }
    }
    

【讨论】:

    猜你喜欢
    • 2015-11-22
    • 2019-05-30
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多