2016-07-22 18 views
8

Tôi có một trường nhập được ánh xạ tới một thực thể trong bộ điều khiển của tôi với một ràng buộc 2 chiều ngModel.Góc 2 thiết lập null làm giá trị chuỗi rỗng cho trường nhập

<input type="text" [(ngModel)]="entity.one_attribute" /> 

Khi tôi khởi tạo bộ điều khiển của tôi, tôi có tổ chức này:

{ one_attribute: null } 

Nếu người dùng bắt đầu để điền vào trong lĩnh vực này nhưng không gửi biểu mẫu ngay lập tức và đổ lĩnh vực này, thực thể của tôi được cập nhật để trở thành:

{ one_attribute: "" } 

Có thể xác định chuỗi rỗng sẽ tự động được thay đổi thành không?

+0

Nhân tiện, tôi biết rằng tôi có thể làm sạch pháp nhân của mình trước khi gửi hoặc thêm sự kiện khóa trên trường của tôi. Nhưng tôi muốn làm điều này mà không cần viết bất kỳ mã nào chỉ cho điều đó. – jobou

+0

Tôi không nghĩ rằng có bất cứ điều gì mà sẽ làm điều này tự động. Tuy nhiên, bạn có thể chia ngModel thành các ràng buộc riêng biệt cho thuộc tính giá trị và sự kiện đầu vào và chỉ cần đặt mô hình thành null nếu giá trị là chuỗi rỗng. –

+1

Điều gì về việc tạo một thành phần sử dụng nội bộ 'đầu vào' và thực hiện logic bên trong nó? Bằng cách đó bạn sẽ không cần phải viết nó mọi lúc. –

Trả lời

11

Sau khi xem một loạt các câu trả lời về ValueAccessorHostListener giải pháp, tôi đã thực hiện một giải pháp làm việc (thử nghiệm với RC1):

import {NgControl} from "@angular/common"; 
import {Directive, ElementRef, HostListener} from "@angular/core"; 

@Directive({ 
    selector: 'input[nullValue]' 
}) 
export class NullDefaultValueDirective { 
    constructor(private el: ElementRef, private control: NgControl) {} 

    @HostListener('input', ['$event.target']) 
    onEvent(target: HTMLInputElement){ 
    this.control.viewToModelUpdate((target.value === '') ? null : target.value); 
    } 
} 

Sau đó sử dụng nó như vậy trên các lĩnh vực đầu vào của bạn:

<input [(ngModel)]="bindedValue" nullValue/> 
+0

Xem [câu trả lời của tôi] (https://stackoverflow.com/a/46835559/1409101) nếu bạn không muốn đánh dấu mọi đầu vào. –

+1

Thiết bị đánh chặn trở lại trong 4.3.4, do đó bạn không cần phải viết chỉ thị cho việc này. –

-2

Tôi đã thực hiện nó trên toàn cầu. Nhưng nó không phải 100%. Tôi không thể tìm thấy phương pháp mà góc 4 gọi JSON.stringify trên cơ thể. Tôi hy vọng ai đó có thể giúp đỡ ở đây. Cho đến khi HttpClient mới trong 4.3 là ra tôi tiếp tục sử dụng một lớp wrapper cho dịch vụ Http. Tôi làm điều này bởi vì không có kẻ can thiệp nào có mặt trong Angular2 và tiến lên. Wrapper của tôi trông giống như thế này.

@Injectable() 
export class MyDao { 
constructor(private http: Http) { 
} 
public get(options?:MyRequestOptions){...} 
public post(url:string,body,options?:MyRequestOptions){ 
    let reqOptions = new BaseRequestOptions(); 
    reqOptions.url = url; 
    reqOptions.params= this.processParams(options); 
    reqOptions.header= this.processHeaders(options); //ex. add global headers 
    reqOptions.body=this.removeEmptyStringsInBody(body); 
    this.http.post(options); 
} 

Cho đến nay rất tốt. Nhưng tôi đã không tìm thấy bất kỳ transformRequest tốt như trong AngularJS, vì vậy cho đến khi tôi tìm thấy nó, tôi đã thực hiện transformEmptyStringAsNull như thế này:

private removeEmptyStringsInBody(body:any) { 
    let bodyTemp= JSON.stringify(body, function (key, value) { 
     return value === "" ? null : value 
    }); 
    return JSON.parse(bodyTemp); 
} 

Tôi biết đó là xấu xí trong cách mà tôi sẽ làm một stringify thêm lại để phân tích một lần nữa. Nhưng tôi không cần phải làm bất cứ điều gì trong phần còn lại của ứng dụng.

+0

Tôi đã tìm ra cách để thực hiện nó trên toàn cầu mà không cần phải gây rối với Http. Xem [câu trả lời của tôi] (https://stackoverflow.com/a/46835559/1409101) để biết chi tiết. –

3

Tôi vừa mới hình thành giải pháp này sau nhiều nghiên cứu. Đó là loại hack since the Angular team doesn't recommend extending DefaultValueAccessor, nhưng nó tự động hoạt động cho mọi đầu vào mà không cần phải đánh dấu từng cái một.

import { Directive, forwardRef, Renderer2, ElementRef, Input } from '@angular/core'; 
import { DefaultValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; 

export const VALUE_ACCESSOR: any = { 
    provide: NG_VALUE_ACCESSOR, 
    useExisting: forwardRef(() => InputExtensionValueAccessor), 
    multi: true 
}; 

@Directive({ 
    selector: 'input:not([type]),input[type=text],input[type=password],input[type=email],input[type=tel],textarea', 
    host: { 
     '(input)': '_handleInput($event.target.value)', 
     '(blur)': 'onTouched()', 
     '(compositionstart)': '_compositionStart()', 
     '(compositionend)': '_compositionEnd($event.target.value)' 
    }, 
    providers: [VALUE_ACCESSOR] 
}) 
export class InputExtensionValueAccessor extends DefaultValueAccessor { 
    // HACK: Allows use of DefaultValueAccessor as base 
    // (https://github.com/angular/angular/issues/9146) 
    static decorators = null; 

    constructor(renderer: Renderer2, elementRef: ElementRef) { 
     super(renderer, elementRef, (null as any)); 
    } 

    registerOnChange(fn: (_: any) => void): void { 
     super.registerOnChange(value => { 
      // Convert empty string from the view to null for the model 
      fn(value === '' ? null : value); 
     }); 
    } 
} 

Điều này phù hợp với tôi trên Angular 4.4.5.

+0

Vẫn nghĩ rằng nó tốt hơn để làm điều đó trong máy đánh chặn –

+1

Tôi không đồng ý. Ý định của tôi là sửa chữa nguyên nhân, không phải là triệu chứng. Điều này cũng cho phép tôi kiểm soát nếu tôi muốn thay đổi các giá trị rỗng nhất định thành 'undefined' để giữ chúng không bị gửi đi. –

Các vấn đề liên quan