使用 ng-content 在父组件中进行模板驱动的表单验证

2024-02-27

过去几天我一直在寻找答案,但找不到解决方案。

我有一个基本页面组件,所有其他页面都扩展了它,因为涉及很多临时页面。在我的场景中,我创建了一个模态和一个 ng-content 选择器,以便在需要时填充输入。

Codes:

基本页面列表.component.html

    <section class="widget animated fadeIn" widget>
    <header>
        <h4 class="page-title" *ngIf="pageType !== PageType.TAB">
            <ng-content select=".page-title"></ng-content>
        </h4>
        <div class="widget-controls">
            <a data-widgster="expand" title="Expand" href="#"><i class="glyphicon glyphicon-chevron-up"></i></a>
            <a data-widgster="collapse" title="Collapse" href="#"><i class="glyphicon glyphicon-chevron-down"></i></a>
        </div>
    </header>

    <div class="widget-body" [ngSwitch]='status'>
        <div class="mt-0 clearfix">
            <alert *ngFor="let toast of alertService.toasts; let i = index" [type]="toast.type + ' alert-sm'" (close)="alertService.closeToast(i)" dismissible="true" dismissOnTimeout="5000">
                <div [innerHTML]="toast.msg"></div>
            </alert>

            <!-- Spinner -->
            <div class="sk-fading-circle" *ngSwitchCase="status === PageStatus.LOADING || status === PageStatus.EASY_LOADING ? status : -1">
                <div class="sk-circle1 sk-circle"></div>
                <div class="sk-circle2 sk-circle"></div>
                <div class="sk-circle3 sk-circle"></div>
                <div class="sk-circle4 sk-circle"></div>
                <div class="sk-circle5 sk-circle"></div>
                <div class="sk-circle6 sk-circle"></div>
                <div class="sk-circle7 sk-circle"></div>
                <div class="sk-circle8 sk-circle"></div>
                <div class="sk-circle9 sk-circle"></div>
                <div class="sk-circle10 sk-circle"></div>
                <div class="sk-circle11 sk-circle"></div>
                <div class="sk-circle12 sk-circle"></div>
            </div>
            <!-- Spinner End -->

            <!--Tables-->
            <div *ngSwitchCase="status == PageStatus.DONE || status === PageStatus.EASY_LOADING ? status : -1">
                <div class="form-control-static">

                    <div class="form-group pull-left">
                        <ng-content select="custom-filter-content"></ng-content>
                    </div>

                    <!-- Search Box -->
                    <div class="form-group pull-right">
                        <div class="input-group">
                            <span class="input-group-addon"><i class="fa fa-search"></i></span>
                            <input type="text" class="form-control" [(ngModel)]="filter.searchTerm"
                                   [disabled]="false"
                                   (keyup.enter)="runQuery()"
                                   placeholder="{{'global.label.search' | translate}}"/>
                            <div class="input-group-btn">
                                <button type="button" class="btn btn-default" (click)="reset()">
                                    <i class="fa fa-refresh text-primary"></i>
                                </button>
                            </div>
                        </div>
                    </div>
                    <!-- Search Box End -->

                    <div *ngIf="isFiltered() && isSearchResultEmpty()">
                        <label>{{'global.label.nodata' | translate}}</label>
                        <ng-content select="table-no-data"></ng-content>
                    </div>
                </div>

                <div *ngIf="isFiltered() && !isSearchResultEmpty()" class="form-control-static">
                    <ng-content select="table-content"></ng-content>
                </div>
            </div>
            <!-- Tables End -->
        </div>

        <!-- Table Buttons -->
        <div class="form-actions">
            <button class="btn btn-inverse" (click)="showModal(ModalState.CREATE)">
                <i class="glyphicon glyphicon-plus-sign text-warning"></i>
                {{'global.label.addNew' | translate}}
            </button>
            <ng-content select="table-buttons"></ng-content>
        </div>
        <!-- Table Buttons End -->
    </div>
</section>

<!-- Modal -->
<div bsModal #modal="bs-modal" data-backdrop="true" data-keyboard="false" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <button (click)="modal.hide()" aria-label="Close" class="close" role="button">
                    <span aria-hidden="true">×</span>
                </button>
                <div [ngSwitch]="modalState">
                    <h4 class="modal-title" *ngSwitchCase="ModalState.CREATE">{{'global.label.addNew' | translate}}</h4>
                    <h4 class="modal-title" *ngSwitchCase="ModalState.UPDATE">{{'global.label.editRecord' | translate}}</h4>
                </div>
            </div>

            <form #recordForm="ngForm" enctype="multipart/form-data">
                <div class="modal-body">
                    <!-- Spinner -->
                    <div class="sk-fading-circle" *ngIf="status === PageStatus.LOADING || status === PageStatus.EASY_LOADING">
                        <div class="sk-circle1 sk-circle"></div>
                        <div class="sk-circle2 sk-circle"></div>
                        <div class="sk-circle3 sk-circle"></div>
                        <div class="sk-circle4 sk-circle"></div>
                        <div class="sk-circle5 sk-circle"></div>
                        <div class="sk-circle6 sk-circle"></div>
                        <div class="sk-circle7 sk-circle"></div>
                        <div class="sk-circle8 sk-circle"></div>
                        <div class="sk-circle9 sk-circle"></div>
                        <div class="sk-circle10 sk-circle"></div>
                        <div class="sk-circle11 sk-circle"></div>
                        <div class="sk-circle12 sk-circle"></div>
                    </div>
                    <!-- Spinner End -->

                    <ng-content select="modal-body-content"></ng-content>

                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-gray" (click)="modal.hide()">
                        {{'global.button.close' | translate}}
                    </button>
                    <span [ngSwitch]="modalState">
                        <button *ngSwitchCase="ModalState.CREATE" role="button" [disabled]="status === PageStatus.LOADING || !recordForm.form.valid" class="btn btn-success" (click)="onAddItem()">
                            <i class="fa fa-spinner fa-spin" [hidden]="status !== PageStatus.LOADING"></i>
                            {{'global.button.save' | translate}}
                        </button>
                        <button *ngSwitchCase="ModalState.UPDATE" role="button" [disabled]="status === PageStatus.LOADING || !recordForm.form.valid" class="btn btn-info" (click)="onUpdateItem()">
                            <i class="fa fa-spinner fa-spin" [hidden]="status !== PageStatus.LOADING"></i>
                            {{'global.button.update' | translate}}
                        </button>
                    </span>
                </div>
            </form>

        </div>
    </div>
</div>

基本页面列表.component.ts

import {PageEvent} from "angular2-datatable-serverpagination";
import {
    OnInit, Component, Input, ViewEncapsulation, ViewChild, Injectable
} from "@angular/core";
import {BasePageService} from "../../service/base-page.service";
import {PaginationResult} from "../../model/pagination-result";
import {BasePageFilter} from "../../model/base-page-filter";
import {BasePageResultItem} from "../../model/base-page-result-item";
import {ModalDirective} from "ng2-bootstrap";
import {AlertService} from "../../../../utils/alert.service";
import * as Models from '../../model/models'
import {NgForm} from "@angular/forms";

export enum PageType {
    DEFAULT,
    TAB
}

export enum PageStatus {
    DONE,
    LOADING,
    EASY_LOADING,
    ERROR
}

export enum ModalState {
    CREATE,
    UPDATE,
    DELETE
}

@Component({
    selector: 'app-base-page-list',
    templateUrl: 'base-page-list.component.html',
    styleUrls: ['../../elements.style.scss'],
    encapsulation: ViewEncapsulation.None
})
export class BasePageListComponent<F extends BasePageFilter, I extends BasePageResultItem, S extends BasePageService<F, I>> implements OnInit {

    @ViewChild("modal")
    modal: ModalDirective;

    @Input("recordForm")
    recordForm: NgForm;

    @Input("formErrors")
    formErrors: any;

    @Input("validationMessages")
    validationMessages: any;

    constructor(public alertService: AlertService) {
    }

    ngOnInit() {
        if (!this.formErrors) {
            this.formErrors = {};

            if (this.validationMessages) {
                for (let key of Object.keys(this.validationMessages)) {
                    this.formErrors[key] = '';
                }
            }
        }
    }

    showModal(state: ModalState, item?) {
        switch (state) {
            case ModalState.CREATE:
                //todo
                break;

            case ModalState.UPDATE:
                //todo
                break;

            case ModalState.DELETE:
                break;

            default:
                state = ModalState.CREATE;
                break;
        }

        this.modalState = state;
        this.modal.show();
    }

}

这是我从另一个页面输入的内容,例如事件列表事件列表.component.html

<app-base-page-list  #basepage [parent]="this" [instanceClassName]="'EventModel'" [validationMessages]="formValidator">
    <div class="page-title">
        {{ 'event.list.title' | translate }}
    </div>

    <app-base-page-filter-field
            [filter]="basepage.filter"
            [labelMessageKey]="'global.label.name'"
            [fieldName]="'_id'"
            [fieldType]="'text'">
    </app-base-page-filter-field>

    <table-no-data></table-no-data>

    <table-content>
        <table [ngSwitch]='basepage.filter.orderByDirection' class="table table-striped table-hover"
               [mfData]="basepage.items" #mf="mfDataTable"
               (mfOnPageChange)="basepage.onPageChange($event)"
               [mfAmountOfRows]="basepage.count"
               [mfActivePage]="basepage.pageNumber"
               [mfRowsOnPage]="basepage.pageSize">
            <thead>
            <tr>
                <th class="hidden-sm-down">
                    <app-base-page-sort-field [filter]="basepage.filter"
                                              [sortChangeListener]="basepage"
                                              [labelMessageKey]="'global.label.name'"
                                              [sortProperty]="'name'">
                    </app-base-page-sort-field>
                </th>
                <th class="hidden-sm-down">
                    <app-base-page-sort-field [filter]="basepage.filter"
                                              [sortChangeListener]="basepage"
                                              [labelMessageKey]="'global.label.startDate'"
                                              [sortProperty]="'startDate'">
                    </app-base-page-sort-field>
                </th>
                <th class="hidden-sm-down">
                    <app-base-page-sort-field [filter]="basepage.filter"
                                              [sortChangeListener]="basepage"
                                              [labelMessageKey]="'global.label.endDate'"
                                              [sortProperty]="'endDate'">
                    </app-base-page-sort-field>
                </th>
                <th class="hidden-sm-down">
                    <app-base-page-sort-field [filter]="basepage.filter"
                                              [sortChangeListener]="basepage"
                                              [labelMessageKey]="'global.label.description'"
                                              [sortProperty]="'description'">
                    </app-base-page-sort-field>
                </th>
                <th class="hidden-sm-down">
                    <app-base-page-sort-field [filter]="basepage.filter"
                                              [sortChangeListener]="basepage"
                                              [labelMessageKey]="'global.label.createdDate'"
                                              [sortProperty]="'createdAt'">
                    </app-base-page-sort-field>
                </th>
                <th>
                    {{'global.label.actions' | translate}}
                </th>
            </tr>
            </thead>
            <tbody>
            <tr *ngFor="let item of mf.data"
                [ngClass]="{'hovered': hoveringItem == item}"
                (mouseover)="hoveringItem = item" (mouseleave)="hoveringItem = null">
                <td>{{item.name}}</td>
                <td>{{item.startDate | date: 'dd.MM.yyyy HH:mm'}}</td>
                <td>{{item.endDate | date: 'dd.MM.yyyy HH:mm'}}</td>
                <td>{{item.description}}</td>
                <td>{{item.createdAt | date: 'dd.MM.yyyy HH:mm'}}</td>
                <td>
                    <app-base-page-action-field
                            [item]="item"
                            [holder]="this">
                    </app-base-page-action-field>
                </td>
            </tr>
            </tbody>
            <tfoot>
            <tr>
                <td colspan="12">
                    <mfBootstrapPaginator [rowsOnPageSet]="[5, 10, 15, 25]"></mfBootstrapPaginator>
                </td>
            </tr>
            </tfoot>
        </table>
    </table-content>

    <table-buttons></table-buttons>

    <!-- Modal -->
    <modal-body-content>
        <div class="row">
            <div class="col-lg-12">
                <app-base-page-input-field [labelMessageKey]="'organization.label'"
                                           [holder]="this"
                                           [fieldName]="'organization'"
                                           [fieldType]="'select'"
                                           [ajaxUrl]="'organization/list'"
                                           [item]="instance"
                                           [required]="true"
                                           [columnClass]="'col-md-3'">
                </app-base-page-input-field>
            </div>
        </div>
        <div class="row">
            <div class="col-lg-12">
                <app-base-page-input-field [labelMessageKey]="'global.label.name'"
                                           [holder]="this"
                                           [fieldName]="'name'"
                                           [fieldType]="'text'"
                                           [item]="instance"
                                           [required]="true"
                                           [validationCheckProperty]="'name'"
                                           [columnClass]="'col-md-3'">
                </app-base-page-input-field>
            </div>
        </div>
        <div class="row">
            <div class="col-lg-12">
                <app-base-page-input-field [labelMessageKey]="'global.label.description'"
                                           [holder]="this"
                                           [fieldName]="'description'"
                                           [fieldType]="'textarea'"
                                           [item]="instance"
                                           [columnClass]="'col-md-3'">
                </app-base-page-input-field>
            </div>
        </div>

        <div class="row">
            <div class="col-lg-12">
                <app-base-page-input-field [labelMessageKey]="'global.label.startDate'"
                                           [holder]="this"
                                           [fieldName]="'startDate'"
                                           [fieldType]="'datetime'"
                                           [item]="instance"
                                           [required]="true"
                                           [columnClass]="'col-md-3'">
                </app-base-page-input-field>
            </div>
        </div>

        <div class="row">
            <div class="col-lg-12">
                <app-base-page-input-field [labelMessageKey]="'global.label.endDate'"
                                           [holder]="this"
                                           [fieldName]="'endDate'"
                                           [fieldType]="'datetime'"
                                           [item]="instance"
                                           [required]="true"
                                           [columnClass]="'col-md-3'">
                </app-base-page-input-field>
            </div>
        </div>
    </modal-body-content>

</app-base-page-list>

一切都呈现完美,但是当涉及到表单验证时。它始终启动 ng-valid 状态。 'app-base-page-input-field' 组件创建输入字段。 这里是:

<div [ngSwitch]="fieldType" [ngClass]="{'form-group' : true}">

    <label *ngIf="labelMessageKey && (fieldType !== 'singleImage' || fieldType !== 'dynamicRow')" class="col-form-label" [for]="fieldName">
        <strong>{{ labelMessageKey | translate }}</strong>
    </label>
    <p *ngSwitchCase="'static'" class="form-control-static">{{item[fieldName]}}</p>

    <input *ngSwitchCase="'text'" [id]="fieldName"  class="form-control" type="text"
           [(ngModel)]="item[fieldName]"
           placeholder="{{ (placeholder || labelMessageKey) | translate }}"
           [name]="fieldName"
           [attr.required]="required ? 'required' : null">
</div>

任何帮助都会很高兴。谢谢。


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ng-content 在父组件中进行模板驱动的表单验证 的相关文章

  • zend框架验证模型中的数据而不是表单中的数据

    使用 Zend Framework 2 在我的应用程序中 要编辑数据库中的数据 可以编译 html 表单或发送 http post 请求 我的服务器作为 Web 服务实现 在第二种情况下 不会呈现表单 问题 如果当服务器收到不是从表单发送而
  • 在单个 WPF 控件中列出所有 Validation.Error?

    我试图找到一种简单的方法来绑定单个控件 例如 TextBlock 或 ListBox 以列出 WPF 表单上的所有验证错误 我能找到的大多数源代码示例只是将一个控件绑定到 Validation Errors 0 ErrorContent 它
  • Angular 2 形式 + OnPush

    我正在编写一个 Angular 2 应用程序 出于性能原因 我尝试在任何地方使用 ChangeDetectionStrategy OnPush 我有一个复杂的组件 需要 OnPush 才能顺利工作 其中包含另一个显示表单的组件 使用 For
  • 如何在休眠中持久保存实体期间验证实体的约束

    我有一个带有字段名称的实体 我希望它不超过255 所以我这样定义它 Entity public class A implements Serializable NotNull Size max 255 private String name
  • JQuery 验证表单数组中的重复项

    我想显示重复或不唯一的值的错误 但我的表单接受输入数组 我已经在 jsfiddle 上检查了这些问题 name week 失败但是name week 工作正常 问题1 https stackoverflow com questions 24
  • 如何在 JavaScript 中验证包含“00:07 PM”的日期?

    有人验证了这种格式的日期吗 2010 年 2 月 9 日 12 07 以前在 javascript 中 javascript Date 对象存在问题 它接受 Feb 9 2010 00 07 PM 作为有效日期 如果你喜欢使用图书馆 dat
  • VueJS - 验证表单文件上传中的文件大小要求

    我正在使用 Bootstrap Vue 表单制作一个简单的表单 用户可以在其中上传文件 有没有办法验证使用 Vue 表单选择的文件的大小 我想阻止用户上传此类文件 我见过this https stackoverflow com questi
  • 以编程方式创建验证列表

    我有一组从外部源进入 VBA 代码的数据 我希望能够分配该数据以用作此工作簿中一张工作表的单元格下拉框中的验证 但是 我不想将该数据复制到工作表中 然后使用命名范围 可能有相当多的数据 而且这感觉不是很有效 我确信一定有办法 但我还没有找到
  • 如何在 PHP 中验证电子邮件? [复制]

    这个问题在这里已经有答案了 如何使用 php5 验证输入值是有效的电子邮件地址 现在我正在使用这段代码 function isValidEmail email pattern a z0 9 a z0 9 a z0 9 a z0 9 a z
  • 如何使用 Cerberus 返回自定义规则名称/错误代码?

    正在验证 csv文件 我想以用户习惯的格式给出验证结果 为了利用Cerberus https docs python cerberus org en stable index html 我让用户在一个中定义验证规则 yaml file 架构
  • LINQ2SQL:如何实现通用最大字符串长度验证?

    LINQ2SQL 中的一个常见问题是 虽然 NET 字符串允许为其变量分配任意长度 但您的数据库可能具有特定的最大长度约束 如 VARCHAR 5 这将导致 SQL 错误消息 字符串或二进制数据将被截断 这是非常没有帮助的 因为它不会告诉您
  • 如何使用第三方 JS 组件进行 Angular2/4 验证

    当谈到 Angular 2 验证时 我看到了不同的方法 基本方法是使用 HTML5 和模板 模型绑定或带有指定验证器的表单 然而 当涉及到特殊规则时 它需要大量编码 并且模板绑定 因此没有表单 通常会导致验证分散在 HTML 和 TS 代码
  • Jquery:表单验证不起作用

    我对 Jquery 很陌生 希望你们能帮助我解决这个 jquery 验证问题 一直在尝试验证表单 但它根本没有验证 它接受我在字段中输入的任何内容 无论我设置什么限制 请帮忙 谢谢 这是我的代码
  • 将 step="1" 放入“datetime-local”输入类型时,jQuery 验证失败

    我在用着https jqueryvalidation org https jqueryvalidation org 表单验证插件 当我把step 1 in a datetime local输入字段显示秒数 如果我使用插件验证该字段 例如 只
  • mat-select 所需的验证不起作用

    我有以下代码
  • 使用 Minitest 测试自定义验证器

    我有多个带有电子邮件验证的模型 因此 我将验证提取到自定义验证器中 我按照以下教程做到了这一点导轨指南 http guides rubyonrails org active record validations html custom va
  • 使用 jQuery 检查输入是否为空

    我有一个表单 我希望填写所有字段 如果单击某个字段然后未填写 我想显示红色背景 这是我的代码 apply form input blur function if input text is empty this parents p addC
  • 为什么验证不起作用并跳转到另一个页面?

    我写了一个customer display php来验证数据 到目前为止只有名字 但无论名字字段是否为空 网页都会跳转到customer search php并且没有更改数据库中的信息 为什么
  • 如何正确清理来自 AngularJS 控制器的无效输入的表单?

    我有一个 AngularJS 表单 其中包含 除其他字段之外 类型之一url 后者很重要 因为这会强制相应的输入成为有效的 URL 在某些条件下 例如 要关闭具有此类表单的模式对话框 我想以编程方式清除该表单 为此 我实现了方法reset基
  • 禁用 notInArray 验证器 Zend Framework 2

    有没有办法在 Zend Framework 2 中禁用 notInArray Validator 互联网上的所有信息都显示如何在 Zend Framework 1 中禁用 notInArray Validator 例如以这种方式 如果您根本

随机推荐