摘要:创建一个工具类,负责提供以及完成拼接参数的工作。根据我们的配置,来创建这个文件。因为是表单提交,所以我们新建一个服务,由它来完成表单提交的最后一步。
使用ng2-admin搭建成熟可靠的后台系统 -- ng2-admin(五) 完善动态表单组件
升级Angular 4.1 -> 4.3(版本大于 4.3.0 可跳过)升级Angular 4.1 -> 4.3
添加 json-server 模拟数据
创建自己的 http
完成一次表单提交
因为 httpClient 支持的最低 Angular 版本为 4.3, 所以需要先升级我们的 Angular
如下图 配置 package.json
然后需要修改一个配置项,兼容到 4.3.0 版本
tsconfig.json 添加一行
"paths": { "@angular/*": ["../node_modules/@angular/*"] }
这样便完成了版本的升级
添加 json-server 模拟数据我们完成一个数据查询,提交需要一些模拟数据,json-server 工具可以帮助我们,全局安装
npm i json-server -g
在 package.json 中的 scripts 添加一行
"db:mock": "json-server --watch ./db/db.json"
我们现在需要创建一个 json 文件,用于装载我们的模拟数据,根据上述命令,在项目根目录创建
db/db.json
{ "user": [ { "id": 1, "firstName": "张小", "emailAddress": "15135131@qq.com", "brave": "solid" } ] }
打开一个命令行窗口,在项目文件夹执行
npm run db:mock
我们的 json-server 就启动了,现在来回到我们的项目
在提交表单之前,我们需要 ajax 去提交我们的数据,这时候涉及到服务,数据验证,处理 response,这时候需要创建一套 http/httpClient 去负责这些任务。
创建一个 http 工具类,负责提供 header, host, 以及完成拼接 url, 参数的工作。 根据我们的 json-server 配置,来创建这个文件。
api/http/http.service.ts
import { Injectable } from "@angular/core"; import { HttpHeaders } from "@angular/common/http"; @Injectable() export class HttpComponentUtil { public headers = new HttpHeaders({ "Content-Type": "application/json" }); private url: string = "http://localhost:3000/"; public getUrl(url: string): string { return this.url + url; } }
创建 http 的统一拦截服务,做统一拦截,并且在未来做一些通用的工作
api/http/noopInterceptor.ts
import { Injectable } from "@angular/core"; import { Observable } from "rxjs/Observable"; import "rxjs/Rx"; import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse } from "@angular/common/http"; @Injectable() export class NoopInterceptor implements HttpInterceptor { intercept( req: HttpRequest, next: HttpHandler ): Observable > { const started = Date.now(); return next .handle(req) .do(event => { if (event instanceof HttpResponse) { const elapsed = Date.now() - started; console.log(`Request for ${req.urlWithParams} took ${elapsed} ms.`); } }); } }
http 的统一拦截,还需要在 appModule.ts 中多带带注册
app.module.ts
@NgModule({ ... providers: [ ... { provide: HTTP_INTERCEPTORS, useClass: NoopInterceptor, multi: true, } ] });
当 http 请求出错时,需要做一些错误处理,现在来创建一个服务,做统一的错误处理
api/http/handle.service.ts
import { Injectable, Inject } from "@angular/core"; import { Location } from "@angular/common"; import { Router, ActivatedRoute, Params } from "@angular/router"; import { Observable } from "rxjs/Observable"; import swal from "sweetalert2"; @Injectable() export class HandleService { constructor( private router: Router, private _location: Location ) { }; // 处理系统错误 handleError(err: any): Observable{ let errMsg = "发生未知错误,请重试"; if (typeof err == "object" && err.status !== undefined) { if (err.status == 404) { errMsg = "服务器处理异常,请重试"; } else if (err.status == 401) { swal("当前页面无权限查看", "", "warning"); this._location.back(); return Observable.empty(); } else if (err.status == 504) { errMsg = "服务器请求超时,请重试"; } else if (err.status == 503) { errMsg = "相关服务正在部署发布,请稍等"; } else { errMsg = err.json().message; } } swal(errMsg, "", "error"); return Observable.empty(); } // 处理returnCode 这里假定接口 200 通过后,后端返回的状态码为 returnCode handleStatus(result: any): Observable { switch ((result.returnCode && String(result.returnCode)) || "201") { case "201": return Observable.of(result); case "1000": return Observable.of(result); case "1001": swal("当前页面无权限查看", "", "warning"); this._location.back(); return Observable.empty(); case "1002": // 数据为空 return Observable.of(result); default: swal("无法识别的错误码,请联系管理员", "", "error"); return Observable.empty(); } } }
上面有两个依赖注入,需要在 providers 注入,现在创建一个文件来提供注入
api/index.ts
import { HttpComponentUtil } from "./http/http.service"; import { HandleService } from "./http/handle.service"; export const API_SERVICE = [ HttpComponentUtil, HandleService ];
pages/pages.module.ts 中注入这两个服务
@NgModule({ imports: [CommonModule, AppTranslationModule, NgaModule, routing], declarations: [Pages], providers: [ ...API_SERVICE ] })
到这里,http 服务创建完成,下半部分在表单提交时完成,属于应用层
完成一次表单提交完成表单提交,需要用到 ajax, 我们将使用 httpClient 完成 ajax 的工作,我们需要先注入 HttpClientModule, 在 nga.module.ts 中注入,这里不贴代码了
注入完成后,现在来开始编写我们的各项请求实例。
因为是表单提交,所以我们新建一个服务,由它来完成表单提交的最后一步。
theme/components/dynamic-form/dynamic-form.service.ts
import { Observable } from "rxjs/Rx"; import { Injectable } from "@angular/core"; import { HttpClient, HttpEvent, HttpHeaders } from "@angular/common/http"; import { HttpComponentUtil } from "../../../pages/api/http/http.service"; import { HandleService } from "../../../pages/api/http/handle.service"; @Injectable() export class DynamicFormService { constructor( private http: HttpClient, private https: HttpComponentUtil, private handleService: HandleService ) {} public getList(url: string, params: {} = {}): Observable{ return new Observable(); } /** * * * @param {string} url * @param {{}} [params={}] 请求入参的 body,参数 * @returns {Observable } 返回一个可供订阅的观察者对象 * @memberof DynamicFormService */ public saveQuery(url: string, params: {} = {}): Observable { let api_url: string = this.https.getUrl(url); // 利用公用的 http 服务,拼接获取url return this.http.post(api_url, params, { headers: this.https.headers }) .map((res: any) => ( this.handleService.handleStatus(res)).value || undefined) // 捕获错误码 .catch(err => this.handleService.handleError(err)); // 捕获系统错误 } }
上面构建了包含一个 saveQuery 功能的服务, 代码已经添加注释,可以仔细研读一下。
saveQuery 的两个参数,params 应该由动态表单直接获取提供,url 应该由页面提供, 所以 DynamicFormComponent 应该接入一个 Input 参数
@Input() config: FormConfig;
dynamic-form/form-base.ts
export interface FormConfig { url: string; }
现在需要在页面中,把 config 参数传入组件
user-add.component.ts
... export class UserAddComponent { public UserAddConfig: FormConfig = { url: "user" } ... }
user-add.component.html
新增用户组件
现在回到组件,我们将完成我们的提交表单操作,现在思考两个问题,提交成功后的操作
成功提示
返回到上一个页面
所以我们的组件应该是
dynamic-form.component.ts
import { Component, Input, OnInit } from "@angular/core"; import { Location } from "@angular/common"; import { FormGroup } from "@angular/forms"; import { QuestionBase } from "../dynamic-form-components/dynamic-form-base/question-base"; import { QuestionControlService } from "./question-control.service"; import { DynamicFormService } from "./dynamic-form.service"; import "style-loader!./dynamic-fom-components.component.scss"; import { FormConfig } from "./form-base"; import swal from "sweetalert2"; @Component({ selector: "dynamic-form", templateUrl: "./dynamic-form.component.html", styleUrls: ["./dynamic-form.component.scss"], providers: [QuestionControlService, DynamicFormService] }) export class DynamicFormComponent implements OnInit { @Input() questions: QuestionBase[] = []; @Input() config: FormConfig; form: FormGroup; payload = ""; constructor( private qcs: QuestionControlService, private service: DynamicFormService, private _location: Location ) {} ngOnInit() { this.form = this.qcs.toFormGroup(this.questions); } onSubmit() { this.payload = JSON.stringify(this.form.value); this.service.saveQuery(this.config.url, this.payload) .subscribe((res: Response) => { console.log(res); swal("success","","success").then(() => { this._location.back(); }); }) } }
这里使用到了 sweetalert2 组件,需要读者自行安装,并且在
pages.component.ts 中引入样式
import "style-loader!sweetalert2/dist/sweetalert2.min.css";
现在打开浏览器,来测试一下我们刚才的页面,测试结果如下
添加成功和失败,都有对应提示,并且提交成功后会返回到上一页,现在来看看 db.json,如下图,数据也被添加进了json!
我们的数据已经存入,下章就来讲解,如何搭建一个动态表格组件,来展示我们的数据,后续会把增删改查功能一一介绍,在介绍完基础组件后,会注入 redux 方便我们的状态管理
(此章代码在ng2-admin 的 httpclient-submit 分支上,可以pull 下来,方便读者练习)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/90639.html
摘要:使用搭建成熟可靠的后台系统三完善动态表单添加样式。下一章会讲解,一个集成的服务,来完成我们的提交,在将来的篇章里会在我们的组件中加入使其变得更加灵活。 使用ng2-admin搭建成熟可靠的后台系统 -- ng2-admin(三) 完善动态表单 添加样式。 抽离组件。 添加组件样式 上一篇文章创建了两个,组件,现在使用bootstrap来给他们添加一些样式 首先需要一个公用的 s...
摘要:使用搭建成熟可靠的后台系统四完善动态表单组件添加正则验证添加错误提示添加正则验证先来设置一些错误提示,以及添加正则验证上一章可能遗留了部分路径错误,可以自行调整邮箱格式不正确请选择这里是提供的一些正则 使用ng2-admin搭建成熟可靠的后台系统 -- ng2-admin(四) 完善动态表单组件 添加正则验证 添加错误提示 添加正则验证 先来设置一些错误提示,以及添加正则验证(...
摘要:使用搭建成熟可靠的后台系统二构建动态表单构建一个动态表单,动态生成控件,验证规则。现在来创建它的子组件从上面的组件可以看出,未来需要添加组件时,只需要添加一种类型,可以用决定显示哪种类型的问题。 使用ng2-admin搭建成熟可靠的后台系统 -- ng2-admin(二) 1.构建动态表单 构建一个动态表单,动态生成控件,验证规则。 创建一个input组件,一个select组件 将...
摘要:注意在配置完成后,需要重新启动项目使配置生效。每一行的内容,由数据内容决定,例如有三条数据,应显示三行数据,数据由组件自身请求获取,所以应该有一个自身的属性用于承载数据。注意这里将换成了,所以组件的也需要替换,否则会报错。 使用ng2-admin搭建成熟可靠的后台系统 -- ng2-admin(六) 完善动态表单组件 先来张本章节最终效果图showImg(https://segmen...
摘要:云函数是万金油为实现用户游戏数据存储和每日任务分发,我们最先用了存储服务和云引擎。不过我们并没有用提供的来直接调用存储服务,而是选择用调用云引擎里面的云函数,然后通过云函数调用存储服务来实现相应的逻辑。 【 玩转 LeanCloud 】开发者投稿分享: 作者:赵天泽 作为一个通过 LeanCloud 入门后端开发的小白,一年多的开发历程让我收获满满。多个项目也在 LeanCloud 可...
阅读 1366·2021-11-22 15:25
阅读 3365·2021-10-21 09:38
阅读 1580·2021-10-19 13:21
阅读 1006·2021-09-06 15:00
阅读 1687·2019-08-30 15:44
阅读 2598·2019-08-29 15:40
阅读 3453·2019-08-29 13:44
阅读 2066·2019-08-26 16:56