使用 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 在父组件中进行模板驱动的表单验证 的相关文章

  • Android - 从服务器获取响应时验证 JSON 以避免 JSONException

    在我的一些与服务器通信并使用 http 获取响应的应用程序中 我使用 json 来格式化数据服务器端 当它到达设备时 我使用类似于我在 stackoverflow 上找到的代码 private class LoadData extends
  • Laravel 验证:对 null 的成员函数调用失败()

    这段代码几天前还可以工作 但我似乎做了一些事情导致它崩溃 我有这条路线 Route post admin routemanagement AdminController addRoute 看起来像这样 public function add
  • JQuery 验证代码不允许删除输入的文本

    我从这个问题借用了一些代码 见回复4 如何使用 jquery 阻止或限制输入字段中的特殊字符 https stackoverflow com questions 895659 how do i block or restrict speci
  • 在 Rails 3.2 + SimpleForm 中显示嵌套表单有错误的字段

    我有一个Flight模型嵌套在一个FlightLog模型 AFlightLog可能包含许多航班 我使用 SimpleForm 进行引导安装 这样当验证失败时 可以用错误类包围带有错误的表单元素 问题是 即使触发了嵌套模型的验证 simple
  • 角度 4 单击按钮功能未触发

    我正在尝试检查文本输入是否为空或不在角度 4 中 我没有为此使用表单 这只是一个输入字段 当我在下面的按钮中执行 addLocaton 函数时 需要进行检查 我的输入字段
  • 使用正则表达式验证器上传文件不适用于仅 Firefox IE

    我有一个带有 RegularExpressionValidator 的 FileUpload 和以下验证表达式 a zA Z 2 w w w gif jpg JPG JPEG GIF jpeg png bmp 3dm 3dmf ai drw
  • JSF 中基于两个组件的组合的验证/转换

    我正在开发一个 JSF Web 应用程序 我需要使用周期性作为数据结构 以下是我使用的 Java 类 public class Periodicity implements Serializable private Integer valu
  • requestValidationMode 2.0 和 4.0 有什么区别

    这是 MSDN 的定义 4 0 默认值 HttpRequest 对象在内部设置一个标志 指示每当访问任何 HTTP 请求数据时都应触发请求验证 这保证了在请求期间访问 cookie 和 URL 等数据之前触发请求验证 配置文件中的页面元素
  • jquery.validate:多个远程规则

    我计划使用两个远程规则验证单个文本字段 更多这样的 form validate rules remote url1 php remote url2 php messages remote Error1 remote Error2 这可能吗
  • 自定义 jQuery 验证 .addMethod

    我有一个表单 可以根据最小 最大长度验证邮政编码 我需要将所有国家 地区的邮政编码最小设置为 5 位数字 澳大利亚除外 澳大利亚需要为 4 位数字 这是我遇到的问题 validator addMethod AusZip function v
  • 对一组复选框使用 HTML5“必需”属性?

    使用支持 HTML5 的较新浏览器 例如 FireFox 4 时 并且表单字段具有属性required required 并且表单字段为空 空白 然后点击提交按钮 浏览器检测到 必填 字段为空 并且不提交表单 相反 浏览器会显示一条提示 要
  • Rails 4 单选按钮表单助手,true 不验证

    我在 needs dist 上附加了简单的是或否单选按钮 当我提交表单时选择 否 它工作得很好 但是当我选择 是 时 它会抛出验证错误吗 它仅在 needs dist gt true 时有效 Model validates presence
  • 如何在 CAST/CONVERT 之前检查 VARCHAR(n) 的 XML 格式是否正确

    我的公司有一个日志表 其中包含VARCHAR N 放置字符串的列 即supposed是 XML 但事实证明它并不总是格式良好的 为了对日志记录进行分析 以确定错误趋势等 我一直在使用LIKE陈述 然而 这非常慢 最近 我发现SQL Serv
  • zend 表单验证

    我想知道 Zend Form 如何验证输入 我的意思是它如何知道要验证哪些输入字段 我查看了 php 全局变量 POST GET 但没有看到任何设置为标识符 例如 的内容 以便了解如何验证 有人能给我推荐一些关于这些东西的指南吗 好吧 找出
  • 具有多个验证组的 Page_ClientValidate() - 如何同时显示多个摘要?

    ASP NET 2 0 假设我有两个验证组 valGrpOne 和 valGrpTwo 以及两个验证摘要 valSummOne 和 valSummTwo 分解部分的原因纯粹是为了美观 一个提交按钮会触发对两组的验证 现在我想触发客户端验证
  • jQuery 验证 - 只显示一条错误消息

    使用 jQuery 验证插件时 有没有办法只显示抛出的最新错误消息 我认为你应该调查一下groups and errorPlacement的选项validate方法 这应该适合你 jQuery 验证 validate 选项 http doc
  • [Bind(Exclude = "AlbumId")] 注解在数据验证中的作用是什么?脚手架是什么意思?

    我按照这个教程 http www asp net mvc tutorials mvc music store mvc music store part 6 http www asp net mvc tutorials mvc music s
  • 在 MATLAB 中验证输入的最佳实践

    在验证 MATLAB 函数中的输入时 什么时候使用 inputParser 比使用断言更好 或者还有其他更好的工具可用吗 我个人发现使用 inputParser 不必要地复杂 对于 Matlab 始终需要检查 3 项内容 存在 类型和范围
  • JavaScript 正则表达式否定精确的字符串匹配

    HTML JavaScript 中有没有办法编写正则表达式来否定精确的字符串匹配 我想确保输入不等于 foo 仅有的 foo 验证必须失败 但是 fooo 必须被允许 换句话说 我正在寻找这个正则表达式的否定
  • codeigniter 动态表单输入名称的表单验证

    我有一个 codeigniter 应用程序 我的视图使用数据库行 ID 附加到输入名称以获取唯一 ID 这允许我在表单操作 即更新 中使用所有输入 我的视图语法 table tr th nbsp th th nbsp th th Custo

随机推荐