响应式表单(表单修改未提交时,存储数据)

响应式表单

响应式表单:使用FormGroup, FormControl,FormArray,FormBuilder 等类构建出的数据对象就是响应式的表单,可动态删除或添加控件。
模板驱动表单:使用ngModel、ngForm进行双向绑定。

项目结构如图:
在这里插入图片描述
array-slave.component.html

<ng-container [formGroup]="validateForm">
    <button nbButton type="button" (click)="addSlave()" style="margin-left: 2rem;font-size: 13px;padding: 7px;background-color: royalblue ;border-color: royalblue;" translate>add slave</button>
    <button nbButton type="button" (click)="selectLanguage('zh-CN')" style="margin-left: 2rem;font-size: 13px;padding: 7px;background-color: saddlebrown ;border-color: saddlebrown;">中文简体</button>
    <button nbButton type="button" (click)="selectLanguage('en-US')" style="margin-left: 2rem;font-size: 13px;padding: 7px;background-color: saddlebrown ;border-color: saddlebrown;">English</button>
    <div formArrayName="slave" *ngFor="let slave of slave?.controls; let slaveIndex = index;">
        <ng-container [formGroupName]="slaveIndex"><br>
            <nb-accordion>
                <nb-accordion-item #item>
                    <nb-accordion-item-header><span translate>Slave</span>{{slaveIndex+1}}
                        <button nbButton type="button" (click)="removeSlave(slaveIndex)" style="margin-left: 2rem;font-size: 13px;padding: 7px;background-color: royalblue ;border-color: royalblue;" translate>remove slave</button>
                        <span *ngIf='val'>
                            <span style="margin: 0 2rem;" *ngIf='val[slaveIndex]' translate>Slave Connection<span>:{{val[slaveIndex]["SlaveConnection"]}}</span></span>
                            <span *ngIf='val[slaveIndex]' translate>Hw Id<span>:{{val[slaveIndex]["HwId"]}}</span></span>
                        </span>
                    </nb-accordion-item-header>
                    <nb-accordion-item-body>
                        <!-- SlaveConnection TcpPort -->
                        <div class="form-group row">
                            <label class="label col-sm-2 col-form-label" >{{ 'Slave Connection' | translate }}</label>
                            <div class="col-sm-4">
                                <input type="text" nbInput  fullWidth required formControlName="SlaveConnection" placeholder="<IPV4 address>"
                                pattern="^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$">
                            </div>
                            <label class="label col-sm-2 col-form-label" translate>Tcp Port</label>
                            <div class="col-sm-2">
                                <input type="text" nbInput fullWidth formControlName="TcpPort">
                            </div>
                        </div>
                        <!-- RetryCount RetryInterval -->
                        <div class="form-group row">
                            <label class="label col-sm-2 col-form-label" translate>Retry Count</label>
                            <div class="col-sm-2">
                                <input type="text" nbInput fullWidth formControlName="RetryCount">
                            </div>
                            <div class="col-sm-2"></div>
                            <label class="label col-sm-2 col-form-label" translate>Retry Interval</label>
                            <div class="col-sm-2">
                                <input type="text" nbInput fullWidth formControlName="RetryInterval">
                            </div>
                        </div>
                        <!-- HwId -->
                        <div class="form-group row">
                            <label class="label col-sm-2 col-form-label" translate>Hw Id</label>
                            <div class="col-sm-5">
                                <input type="text" nbInput fullWidth required formControlName="HwId" placeholder="PowerMeter-0a:01:01:01:01:01">
                            </div>
                            <div class="col-sm-2">
                                <button nbButton type="button" (click)="addopItem(slaveIndex)" style="display: inline-block;margin-left: 2rem;font-size: 12px;padding: 6px;background-color: teal;border-color: teal;" translate>add operation</button>
                            </div>
                        </div>
                        <!-- Operations -->
                        <div formArrayName="Operations" *ngFor="let item of slave.get('Operations')?.controls; let opIndex = index;">
                            <ng-container [formGroupName]="opIndex">
                                <nb-accordion>
                                    <nb-accordion-item #item>
                                        <nb-accordion-item-header><span translate>Operation</span>{{opIndex+1}}
                                            <button nbButton type="button" (click)="removeopItem(slaveIndex,opIndex)" style="margin-left: 2rem;font-size: 12px;padding: 6px;background-color: teal;border-color: teal;" translate>remove operation</button>
                                        </nb-accordion-item-header>
                                        <nb-accordion-item-body>
                                            <!-- PollingInterval UnitId -->
                                            <div class="form-group row">
                                                <label class="label col-sm-2 col-form-label" translate>Polling Interval</label>
                                                <div class="col-sm-4">
                                                    <input type="text" nbInput fullWidth formControlName="PollingInterval">
                                                </div>
                                                <label class="label col-sm-2 col-form-label" translate>Unit Id</label>
                                                <div class="col-sm-4">
                                                    <input type="text" nbInput fullWidth formControlName="UnitId">
                                                </div>
                                            </div>
                                            <!-- StartAddress Count -->
                                            <div class="form-group row">
                                                <label class="label col-sm-2 col-form-label" translate>Start Address</label>
                                                <div class="col-sm-4">
                                                    <input type="text" nbInput fullWidth formControlName="StartAddress">
                                                </div>
                                                <label class="label col-sm-2 col-form-label" translate>Count</label>
                                                <div class="col-sm-4">
                                                    <input type="text" nbInput fullWidth formControlName="Count">
                                                </div>
                                            </div>
                                            <!-- CorrelationId DisplayName -->
                                            <div class="form-group row">
                                                <label class="label col-sm-2 col-form-label" translate>Correlation Id</label>
                                                <div class="col-sm-4">
                                                    <input type="text" nbInput fullWidth formControlName="CorrelationId">
                                                </div>
                                                <label class="label col-sm-2 col-form-label" translate>Display Name</label>
                                                <div class="col-sm-4">
                                                    <input type="text" nbInput fullWidth formControlName="DisplayName">
                                                </div>
                                            </div>
                                        </nb-accordion-item-body>
                                    </nb-accordion-item>
                                </nb-accordion>
                            </ng-container>
                        </div>
                    </nb-accordion-item-body>
                </nb-accordion-item>
            </nb-accordion>
        </ng-container>
    </div>
</ng-container><br>

array-slave.component.ts

import { Component, OnInit, Input,  } from "@angular/core";
import { FormBuilder, NgForm, FormArray, FormGroup, Validators } from "@angular/forms";
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'ngx-array-slave',
  templateUrl: './array-slave.component.html',
  styleUrls: ['./array-slave.component.scss'],
})
export class ArraySlaveComponent implements OnInit {
  @Input() name: string;
  @Input() form: NgForm; // 把父级的form拿到 用于插入这个父级form
  public validateForm : FormGroup;
  public data2:any;
  // 用于在html中显示slave connection及hw id
  public val:any;
  
  constructor(private fb: FormBuilder, public translate: TranslateService) {
    this.validateForm = this.fb.group({
      slave : this.fb.array([
        this.fb.group({
          SlaveConnection: ["", Validators.required],
          TcpPort: "502",
          RetryCount: "10",
          RetryInterval: "100",
          HwId: ["", Validators.required],
          Operations: this.fb.array([
            this.fb.group({
              PollingInterval: "",
              UnitId: "",
              StartAddress: "",
              Count: "",
              CorrelationId: "",
              DisplayName: "",
            })
          ]),
        })
      ])
    })
    
    // 表单数据发生变化时,将data赋值给data2(valueChanges只能写在constructor中)
    this.validateForm.valueChanges.subscribe(data=>{
      this.data2 = data;
      localStorage.setItem("slave",JSON.stringify(this.data2["slave"]));
    });
  }

  ngOnInit() {
    // 判断localstorage里是否有数据
    if(localStorage.getItem("slave")){
      var obj = localStorage.getItem('slave');
      var objs = JSON.parse(obj);
      this.val = objs;
      // console.log(obj);
      // 判断有几条slave,第一条赋值,后面的添加到表单中
      for(var i=0;i<objs.length;i++){
        if(i==0){
          this.slave.setValue([{
            SlaveConnection: objs[0]["SlaveConnection"],
            TcpPort: objs[0]["TcpPort"],
            RetryCount: objs[0]["RetryCount"],
            RetryInterval: objs[0]["RetryInterval"],
            HwId: objs[0]["HwId"],
            Operations: ([{
              PollingInterval: "",
              UnitId: "",
              StartAddress: "",
              Count: "",
              CorrelationId: "",
              DisplayName: "",
              }])
          }]);
          var ops = objs[i]["Operations"];
          if(ops.length > 0){
            for(var j=0;j<ops.length;j++){
              if(j==0){
                (this.slave.at(i).get('Operations') as FormArray).setValue([{
                      PollingInterval: ops[j]["PollingInterval"],
                      UnitId: ops[j]["UnitId"],
                      StartAddress: ops[j]["StartAddress"],
                      Count: ops[j]["Count"],
                      CorrelationId: ops[j]["CorrelationId"],
                      DisplayName: ops[j]["DisplayName"],
                }])
              }else{
                (this.slave.at(i).get('Operations') as FormArray).push(
                  this.fb.group({
                    PollingInterval: ops[j]["PollingInterval"],
                    UnitId: ops[j]["UnitId"],
                    StartAddress: ops[j]["StartAddress"],
                    Count: ops[j]["Count"],
                    CorrelationId: ops[j]["CorrelationId"],
                    DisplayName: ops[j]["DisplayName"],
                  })
                )
              }
            }
          }else{
            (this.slave.at(i).get('Operations') as FormArray).removeAt(0);
          }
        }else{
          this.slave.push(
            this.fb.group({
              SlaveConnection: objs[i]["SlaveConnection"],
              TcpPort: objs[i]["TcpPort"],
              RetryCount: objs[i]["RetryCount"],
              RetryInterval: objs[i]["RetryInterval"],
              HwId: objs[i]["HwId"],
              Operations: this.fb.array([
                this.fb.group({
                  PollingInterval: "",
                  UnitId: "",
                  StartAddress: "",
                  Count: "",
                  CorrelationId: "",
                  DisplayName: "",
                })
              ]),
            })
          );
          var ops = objs[i]["Operations"];
          if(ops.length > 0){
            for(var j=0;j<ops.length;j++){
              if(j==0){
                (this.slave.at(i).get('Operations') as FormArray).setValue([{
                      PollingInterval: ops[j]["PollingInterval"],
                      UnitId: ops[j]["UnitId"],
                      StartAddress: ops[j]["StartAddress"],
                      Count: ops[j]["Count"],
                      CorrelationId: ops[j]["CorrelationId"],
                      DisplayName: ops[j]["DisplayName"],
                }])
              }else{
                (this.slave.at(i).get('Operations') as FormArray).push(
                  this.fb.group({
                    PollingInterval: ops[j]["PollingInterval"],
                    UnitId: ops[j]["UnitId"],
                    StartAddress: ops[j]["StartAddress"],
                    Count: ops[j]["Count"],
                    CorrelationId: ops[j]["CorrelationId"],
                    DisplayName: ops[j]["DisplayName"],
                  })
                )
              }
            }
          }else{
            (this.slave.at(i).get('Operations') as FormArray).removeAt(0);
          }
        }
      }
    }
    // 将validateForm表单传给父级的form
    this.form.control.addControl(this.name, this.validateForm);
  }

  get slave() {
    return this.validateForm.get("slave") as FormArray;
  }
  // slave增加及删除
  addSlave(): void{
    this.slave.push(
      this.fb.group({
        SlaveConnection: ["", Validators.required],
        TcpPort: "502",
        RetryCount: "10",
        RetryInterval: "100",
        HwId: ["", Validators.required],
        Operations: this.fb.array([
          this.fb.group({
            PollingInterval: "",
            UnitId: "",
            StartAddress: "",
            Count: "",
            CorrelationId: "",
            DisplayName: "",
          })
        ]),
      })
    )
  }
  removeSlave(index: number) {
    this.slave.removeAt(index);
  }

  // op增加及删除
  addopItem(slaveIndex: number): void{
    (this.slave.at(slaveIndex).get('Operations') as FormArray).push(
      this.fb.group({
        PollingInterval: "",
        UnitId: "",
        StartAddress: "",
        Count: "",
        CorrelationId: "",
        DisplayName: "",
      })
    )
  }
  removeopItem(slaveIndex: number,opIndex: number) {
    (this.slave.at(slaveIndex).get('Operations') as FormArray).removeAt(opIndex);
  }

  // 设置语言
  public selectLanguage(lang) {
    this.translate.use(lang);
    // 更新当前记录的语言
    localStorage.setItem('currentLanguage', lang)
  }
}

array-slave.component.scss

nb-accordion{
    // 必须填写的样式
    // .ng-valid[required], .ng-valid.required{
    //     border-left: 5px solid #42a948;
    // }
    .ng-invalid:not(form){
        border-left: 5px solid #a94442;
    }
}

modbus.component.html

<div class="row">
    <div class="col-md-9">
        <nb-card>
            <nb-card-header>modbus协议</nb-card-header>
            <nb-card-body style="padding: 0.5rem;">
                <form novalidate style="margin-bottom: 1rem;" #slavesForm="ngForm">
                    <ngx-array-slave name="slaves" [form]="slavesForm"></ngx-array-slave>
                    <!-- 保存 -->
                    <button nbButton type="button" [disabled]="!slavesForm?.valid" (click)="onSubmit(slavesForm)" style="margin-left: 2rem;margin-top: 0.5rem;font-size: 13px;padding: 7px;" translate>submit</button>
                </form>
            </nb-card-body>
        </nb-card>
    </div>
</div>

modbus.component.ts

import { Component, OnInit, SimpleChanges } from '@angular/core';
import { NgForm } from '@angular/forms';
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Component({
  selector: 'ngx-modbus',
  templateUrl: './modbus.component.html',
  styleUrls: ['./modbus.component.scss']
})
export class ModbusComponent implements OnInit {
  private SlaveConfigs;

  // get请求数据 - 获取数组中数据条数
  public list:any={};
  public num:any;
  constructor(public http:HttpClient) {
    let api = 'assets/admin-data/system-configuration.json';
    this.http.get(api).subscribe(resp =>{
      var propertiesdesired = resp['properties.desired'];
      this.SlaveConfigs = propertiesdesired["SlaveConfigs"];
      // 计算json数据中slave的个数
      var count=0;
      for(var key in this.SlaveConfigs){
          count++;
      }
      this.num = count;
      // console.log(this.num);
    });
  }

  ngOnInit() {
  }
  
  // 提交表单
  onSubmit(form: NgForm){
    // 获取表单数据
      const params = form.control.get('slaves').get('slave').value;
    // console.log(params);
    // 判断是否有slave
    if(params.length == 0){
      alert("您没有添加Slave");
    }
    // 判断是否已经提交了256条slave,如果num >= 256
    if(this.num >= 256){
      alert("您已添加256条Slave");
    }else{
      // 请求头
      const httpOptions = {
        headers: new HttpHeaders({
          'Content-Type':  'application/json',
        })
      };
      for(var i=0;i<params.length;i++){
        // post提交数据 - json-server建虚拟服务器环境
        let api = 'http://localhost:3000/properties.desired';

        // op01 op01...
        var Operations = {};
        var ops = params[i]["Operations"];
        var opNum = ops.length;
        for(var j=0; j<opNum; j++){
          let num2:any = j+1;
          if(num2 < 10){
            num2 = '0' + num2;
          }else{
            num2 = num2;
          }
          Operations["Op"+num2] = ops[j]
          // console.log(ops[j]);
        }
        // console.log(opNum, ops);
        params[i]["Operations"] = Operations;
        // console.log(this.Operations);

        this.num ++;
        // 改为slave01 02 03...格式
        if(this.num < 10){
          this.num = '0' + this.num;
        }else{
          this.num = this.num;
        }
        this.SlaveConfigs['Slave'+this.num] = params[i];
        // console.log(this.SlaveConfigs);
        this.http.patch(api, {"SlaveConfigs" : this.SlaveConfigs}, httpOptions).subscribe(resp =>{
        });
      }
      // 将localstorage中缓存的数据删除
      localStorage.removeItem("slave");
    }
  }
}

modbus.component.scss

nb-card{
    // 必须填写的样式
    // .ng-valid[required], .ng-valid.required{
    //     border-left: 5px solid #42a948;
    // }
    .ng-invalid:not(form){
        border-left: 5px solid #a94442;
    }

    // op1 op2样式
    .opStyle{
        font-weight: 600;
        display: inline-block;
        width: 100%;
        margin-bottom: 1.2rem;
        padding-bottom: 0.8rem;
        border-bottom: 1px solid #edf1f7;
    }
}
上传的数据在这里

使用json-server虚拟服务器

npm install -g json-server
json-server --watch modbus.json

modbus.json

{
  "properties.desired": {
    "PublishInterval": "5000",
    "Version": "1",
    "SlaveConfigs": {
    }
  }
}

国际化(i18n)

在项目的assets目录下新建i18n文件夹,如图:
在这里插入图片描述
en-US.json

{
    "Slave":"Slave",
    "add slave": "add slave",
    "remove slave": "remove slave",
    "Slave Connection": "Slave Connection",
    "Tcp Port": "Tcp Port",
    "Retry Count": "Retry Count",
    "Retry Interval": "Retry Interval",
    "Hw Id": "Hw Id",

    "Operation":"Operation",
    "add operation":"add operation",
    "remove operation":"remove operation",
    "Polling Interval": "Polling Interval",
    "Unit Id": "Unit Id",
    "Start Address": "Start Address",
    "Count": "Count",
    "Correlation Id": "Correlation Id",
    "Display Name": "Display Name",

    "submit":"submit"
}

zh-CN.json

{
    "Slave":"从机",
    "add slave": "添加从机",
    "remove slave": "移除从机",
    "Slave Connection": "从机连接",
    "Tcp Port": "tcp端口",
    "Retry Count": "重试计数",
    "Retry Interval": "重试间隔",
    "Hw Id": "硬件标识",

    "Operation":"操作",
    "add operation":"添加操作",
    "remove operation":"删除操作",
    "Polling Interval": "轮询间隔",
    "Unit Id": "单位编号",
    "Start Address": "起始地址",
    "Count": "总数",
    "Correlation Id": "关联ID",
    "Display Name": "显示名称",

    "submit":"提交"
}
效果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值