【问题标题】:How to get values with Directive & ngModel with Angular 4如何使用 Angular 4 使用 Directive 和 ngModel 获取值
【发布时间】:2018-01-31 15:09:11
【问题描述】:

我在 Angular 2 中创建了一个指令,它正在初始化 Summernote 文本编辑器,该编辑器运行良好,但我无法获得它的值,它总是使用 ngModel 返回 undefined

指令代码:

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

declare var $: any;

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

export class summernoteDirective {

    @Input() config;

    element:any;

    constructor(el: ElementRef) {
        this.element = el.nativeElement;
    }

    ngOnInit()
    {
        $(this.element).summernote(this.config);
    }
}

组件代码 HTML:

<input type="text" name="PostTitle" [(ngModel)]="PostTitle" 
       class="form-control" placeholder="Post title">
<textarea name="PostContent" [(ngModel)]="PostContent" 
       summernote [config]="options"></textarea>
<button (click)="submitPost(PostTitle,PostContent);" 
        class="btn btn-primary" data-toggle="dropdown">Post</button>

组件ts代码:

submitPost(PostTitle,PostContent)
{
    console.log(PostTitle);
    console.log(PostContent);
}

第二个控制台 PostContent 总是返回 undefined 是否有任何方法可以使用指令获取按钮单击时的值

【问题讨论】:

  • 您可以创建一个 plnkr 或 stackblitz 来演示这一点。
  • 需要自己编写controlvalueaccessor来同步控制值和ngModel

标签: angular summernote


【解决方案1】:

你可以试试这个包吗ng2 summernote

【讨论】:

  • 是的,它不工作,有 15 个问题都是开放的
【解决方案2】:

我不太清楚您要做什么。为什么选择 jQuery?它完全没有必要,我实际上不确定它是否会在这种情况下做任何事情,但它绝对没有任何帮助。

不过,我不太了解指令和组件之间的关系。如果您只是想打印/访问组件中的 PostContent 和 PostTitle,则根本不需要指令。

另一个问题是,要在声明后立即访问模板中 ngModel 声明的变量,我认为您需要使用不同的符号,使用 # 来表示本地模板变量。这将使其立即可供相邻元素使用。

试试这个 -

<input type="text" name="PostTitle" ngModel #PostTitle="ngModel" 
   class="form-control" placeholder="Post title">
<textarea name="PostContent" #PostContent="ngModel" ngModel
   summernote [config]="options"></textarea>
<button (click)="submitPost(PostTitle,PostContent);" 
    class="btn btn-primary" data-toggle="dropdown">Post</button>

也许这会有所帮助。

我不清楚你在指令中要做什么,但不管是什么,如果你正在访问注入的元素 Ref,你可能应该等到 EDITED(不,你可以在指令中使用 ngOnInit,使用正如另一位评论者指出的那样,在查看组件的 init 之后,元素 ref 立即在指令中可用)

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

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

export class summernoteDirective {

    @Input() config;

    constructor(private el: ElementRef) {  }

    ngOnInit() {
         console.log(this.config)  <- should print whatever is being sent as input to config property
    }

    ngOnInit()   // edited this back to ngOnInit(), commenter below is right- you dont have to use ngAfterViewInit to access ElementRef's if they are being injected into a directive. They are available immediately
    {
        let buttonId = this.el.nativeElement.id; // random example

    }
}

注入 elementRef 基本上可以让您访问放置指令的 textarea 对象的所有 DOM 属性。如果您通过 id 查询该 textarea 元素,它或多或少会为您提供 jQuery 将给您的内容。您可以使用 this.el.nativeElement.attributeNameHere 访问/设置大多数属性(尽管更好的选择是在必要时使用 Angular 的 Renderer2 类进行 DOM 操作,以防止与浏览器 DOM 紧密耦合) 不需要单独的元素属性或 jQuery。通常,输入在 ngOnInit() 时间解析和可用,DOM 属性/元素在 ngAfterViewInit() 时间解析和可用。

【讨论】:

  • ElementRef 在构造函数中可用,他使用 jquery 因为 Summernote 使用它
  • #PostContent="ngModel" 为什么会出现在这里?他只想获得价值而不是NgModel指令
  • 它与 [(ngModel)] 做同样的事情,但在流程中定义了一个名为 PostContent 的本地模板变量,其他模板元素可以访问该变量。它只是使用 ngModel 的不同表示法,它仍然会将 textarea 的内容绑定到名为 PostContent 的变量,反之亦然。如果使用香蕉盒表示法,则只能访问组件中声明的变量,或者如果将整个组包装在 NgForm 元素中,则可以使用表单名称访问模板中的各个 ngModel 属性。跨度>
  • 我仍然认为没有必要。通过注入 ElementRef,您基本上已经提供了 jQuery 将提供给您的内容。尽管关于 ElementRef,您是正确的,但我的错误。只需要在组件中使用 AfterViewInit 即可访问 nativeElements。
【解决方案3】:

我不确定它是否正确,但这个方法对我有用:

import { Directive, ElementRef, Input, Output, EventEmitter } from '@angular/core';
import { NgModel } from '@angular/forms';
declare var $: any;

@Directive({ 
    selector: '[summernote]',
    providers: [NgModel]
})

export class summernoteDirective {

    @Input() config;

    element:any;
    model:any;

    constructor(el: ElementRef, ngModel: NgModel) {
        this.element = el.nativeElement;
        this.model = ngModel;
    }

    ngOnInit()
    {
        let that = this;
        $(this.element).summernote(this.config);
        $(this.element).on('summernote.change',function(e){
            that.model.update.emit(e.currentTarget.value);
        });
    }
}

我导入 NgModel 并在 Summernote 更改触发时对其进行更新。

【讨论】:

    猜你喜欢
    • 2021-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-05
    • 2018-01-29
    • 1970-01-01
    • 2017-05-31
    • 2020-07-14
    相关资源
    最近更新 更多