当前位置: ManBetXapp > 百科 > 科技 >正文

Angular如何进行列表排序

人气:407 ℃ /2023-06-16 05:17:51

工具/材料

SublimeText

操作方法

打开SublimeText软件,新建一个目录结构,在目录里面添加angular的js库文件和html文件,如下图所示

接下来我们在html文件里面通过script标签引入angular的js脚本文件,如下图所示

然后我们在脚本标签里面实现一个控制器,并且在scope上下文中准备一个列表数据,如下图所示

接下来需要准备table列表,在table列表里面通过ng-repeat命令遍历准备好的数组,如下图所示

准备好页面以后,我们运行程序,你就会在页面中看到如下图所示的列表数据,这个数据和你刚才准备时的顺序是一样的

接下来我们在列表里面通过orderBy命令来对列表进行排序,这里是按年龄排序的,所以在中括号里面要跟上age字段,如下图所示

最后我们重新运行页面,你就会看到列表里面的数据已经按照年龄从小到大进行排列了,如下图所示

angular怎么把表单放到中间

Angular 自定义表单控件和嵌套表单组变得简单

如何使您的表单更可重用、拆分它们并使其更具动态性。

对于简单的案例,表格可以轻而易举。 但是,一旦您开始构建比注册表更复杂的东西,事情就会变得非常复杂。

当表单遇到困难时,有一些事情会让您的生活更轻松,例如自定义表单控件和嵌套表单组。 这将是本文的重点。 如何使我们的表单更可重用,如何拆分它们,并使它们更具动态性。

那么,让我们开始吧!

自定义表单控件(控件值访问器)

自定义表单控件是与 Angular Forms API 兼容的指令。 兼容是指它可以像任何其他原生表单控件元素一样在表单中使用。

或者等效地使用模板驱动的表单。

这看起来有多整洁?

最重要的是,这个自定义表单控件可以实现为与表单模块无关。 它可以与模板驱动的表单和反应式表单一起使用。

现在,假设我们的应用程序使用了很多表单,而这些表单又包含很多文本字段。 这些文本字段中的大多数是相同的,并且需要具有一致的显示和行为。

让我们从构建一个简单的自定义表单控件开始,称为 required-field。 顾名思义,它将是一个必需的输入字段,显示适当的验证消息,并根据其状态(有效或无效)调整其样式。

为此,我们需要实现 3 件事。

1. 支持原生文本元素所做的一切

为了支持原生表单元素所做的一切,我们需要构建一个 ControlValueAccessor (CVA)。 此接口充当表单控件的视图和模型之间的桥梁。

这两个需要同步才能使表单控件正常工作。 当您在字段中键入内容时,需要将值发送回模型。 分别地,当您以编程方式设置值时,该更改需要反映在视图中。

实现 ControlValueAccessor 接口很简单。 我们只需要实现 3 个强制方法:

  • writeValue(value) — 当请求从模型到视图的编程更改时,由表单 API 调用以写入视图
  • registerOnChange(fn) — 提供一个回调函数 fn,只要我们的输入值发生变化就应该调用它
  • registerOnTouched(fn) — 提供一个回调函数 fn,当我们的输入被认为是触摸或模糊时应该调用它

和可选的1个:

  • setDisabledState(value) — 当控件状态更改为“禁用”或从“禁用”更改时由表单 API 调用

@ViewChild('input') input: ElementRef;onChange: (value: any) => void = () => {};onTouched: () => void = () => {};disabled: boolean;writeValue(value: any): void { this.input.nativeElement.value = value;}registerOnChange(fn: (value: any) => void): void { this.onChange = fn;}registerOnTouched(fn: () => void): void { this.onTouched = fn;}setDisabledState(disabled: boolean): void { this.disabled = disabled;}

上一个片段中发生了一些事情。 我们使用 writeValue 将新值传递给显示视图。 我们使用 setDisabledState 来存储禁用状态。 最后,我们存储 registerOnChange 和 registerOnTouched 提供的回调函数。

在模板 HTML 文件中,我们在 (input) 和 (blur) 上调用存储的回调函数,以允许表单 API 自行更新。

我们的 CVA 已准备好使用,我们需要提供它。 我们需要这样做,以便像 NgModel 和 FormControlName 这样的表单控制指令可以将我们的组件识别为值访问器。

@Component({ selector: 'required-field', templateUrl: './required-field.component.html', styleUrls: ['./required-field.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, multi: true, useExisting: RequiredFieldComponent } ]})export class RequiredFieldComponent implements OnInit, ControlValueAccessor { //... }

2. 应用所需的验证

您的第一个想法可能是将 required 属性添加到内部文本字段。 但这不会像您期望的那样工作。

首先,我们不知道也不应该对组件视图下面的内容做出假设。 它可以是不支持表单验证属性的任何东西,例如 div 和 span。

最重要的是,回想一下我们如何需要实现一个特定的通信“协议”,即 CVA 接口,以支持原生表单元素功能? 好吧,我们也需要使用相应的协议来支持验证。

我们需要实现 Validator 接口,它有 1 个强制方法:

  • validate(ctrl: AbstractControl) — 对提供的控件执行同步验证

validate(control: AbstractControl): ValidationErrors | null { return Validators.required(control);}

而已! 我们的验证器已经可以使用了,我们需要提供它。 我们需要这样做,以便像 NgModel 和 FormControlName 这样的表单控制指令可以将我们的组件识别为验证器。

@Component({ selector: 'required-field', templateUrl: './required-field.component.html', styleUrls: ['./required-field.component.scss'], providers: [ { provide: NG_VALIDATORS, multi: true, useExisting: RequiredFieldComponent } ]})export class RequiredFieldComponent implements OnInit, Validator { //... }

3.控件无效时显示错误信息并调整其样式

在我们之前的步骤中,用户可以在这个控件之上添加我们不知道的任何自定义验证。 在这种情况下,我们需要获取下面的模型并检查它是有效还是无效。

显而易见的方法是创建一个输入并通过表单控件实例本身。

那会很好用。 除了它会首先达到创建自定义表单控件的目的。 如果每次都必须通过控件,一段时间后它开始变得有点烦人。

相反,我们想要一种在内部访问表单控件而不需要用户传入的方法。但是,怎么做呢? 进入依赖注入!

我们还说过,我们的自定义表单控件将与表单模块无关,不是吗?

为了实现这一点,我们需要为模板驱动的表单注入 NgControl 而不是 NgModel 或为响应式表单注入 FormControlName。 我们可以这样做,因为 NgModel 和 FormControlName 都是 NgControl 的子类,并提供自己作为 NgControl。

constructor(@Self() public controlDir: NgControl) { }

他们称之为简单的例子?这个@Self() 装饰器是什么?

我们使用 @Self() 装饰器将范围限制为我们当前所在的元素。这是必要的,因为如果我们的自定义表单控件包装在其他人的表单控件中,我们可能会到达并获得一个错误的表单控件实例。

另一件事是 NgControl 正在注入值访问器和验证器。还记得我们说过我们需要提供我们的组件作为值访问器和验证器吗?

好吧,我们不能同时做这两件事!

如果我们注入 NgControl 并且 NgControl 正在注入值访问器,其中包括我们提供的组件,那就是循环依赖!由于我们需要掌握模型,我们确实需要注入 NgControl。因此,我们应该删除提供者以避免循环依赖。

所以现在我们的工作是使用正确的值访问器和验证器正确设置 NgControl。幸运的是,这很容易做到。

对于值访问器部分,我们只需将控制指令的 valueAccessor 属性设置为此。

constructor(@Self() public controlDir: NgControl) { controlDir.valueAccessor = this;}

对于验证器部分,我们可以以编程方式添加验证器。

ngOnInit(): void { const control = this.controlDir.control; let validators = control.validator ? [control.validator, Validators.required] : Validators.required; control.setValidators(validators); control.updateValueAndValidity();}

我们还需要修改 writeValue 方法的实现,使其使用注入的控制指令。

writeValue(value: any): void { value && this.controlDir.control.setValue(value, { emitEvent: false });}

最后,在模板文件中,我们现在可以确定何时显示验证错误消息。 在我们的例子中,如果控件被触摸并且无效。

This field is required!

注意:虽然也有一个无效属性,但我们仍然希望坚持使用 !valid 选项,这样我们就可以支持异步验证器。 这是因为异步验证器在处理时处于待处理状态。 因此,当控件处于挂起状态时,它既不是有效的也不是无效的。 所以我们需要专门说“无效”。

嵌套表单组(复合值访问器)

我们已经研究了如何使用单个输入字段创建自定义表单控件。 但是,如果我们需要一遍又一遍地使用多个输入、一组字段怎么办? 例如,如果我们需要在应用程序的不同位置填写个人信息字段怎么办?

我们复制粘贴吗? 绝不!

相反,我们可以使用我们学到的知识来创建复合 CVA。 让我们创建一个名为personal 的新组件。 我们还可以在新组件中使用我们之前的自定义表单控件必填字段,以使事情变得更容易!

Personal Information

我们对自定义表单控件进行了两次修改。 我们为组件引入了一个名为 placeholder 的输入和一个名为 blur 的输出。 输出对于将输入字段的 onTouched 事件从必填字段内冒泡到其父级是必需的。

这个组件的 TypeScript 文件也有相当多的变化。 我们将一一介绍它们。

首先,我们需要定义表单及其验证。

form: FormGroup;genderOptions: string[] = [ 'Female', 'Male', 'Non-binary', 'Gender non-conforming', 'Prefer not to say', 'Other'];subscriptions: Subscription;constructor(private fb: FormBuilder) { this.subscriptions = new Subscription();}ngOnInit(): void { this.form = this.fb.group( { first: ['', Validators.required], last: ['', Validators.required], gender: ['', Validators.required], genderOther: ['', Validators.required], }, { validators: this.allRequiredFieldsFilled } );}allRequiredFieldsFilled(control: AbstractControl): ValidationErrors | null { const controlValue = control.value; const isValid = controlValue.first && controlValue.last && controlValue.gender && (controlValue.gender !== 'Other' || controlValue.genderOther); return isValid ? null : { required: true };}ngOnDestroy(): void { this.subscriptions.unsubscribe();}

所有字段都是必需的,如果用户为性别字段选择“其他”选项,他/她需要通过一个额外的字段来指定性别,这也是必需的。

接下来,我们需要实现 CVA 接口方法。

onTouched: () => void = () => {}; onChange: (value: any) => void = () => {}; writeValue(value: any): void { value && this.form.setValue(value, { emitEvent: false }); } registerOnChange(fn: (value: any) => void): void { this.subscriptions.add(this.form.valueChanges.subscribe(fn)); } registerOnTouched(fn: () => void): void { this.onTouched = fn; } setDisabledState(disabled: boolean): void { disabled ? this.form.disable() : this.form.enable(); }

我们修改方法以使用表单变量。 主要区别在于 registerOnChange 方法。 回想一下,这个方法为我们提供了当我们的输入值改变时应该调用的回调。 不同的是,现在输入是整个表单。 因此,我们最好的选择是在 valueChanges 发出时调用回调。

我们还需要实现 Validator 接口。

validate(control: AbstractControl): ValidationErrors | null { return this.allRequiredFieldsFilled(control); }

现在,你可能会想,这有必要吗? 我们不是已经在表单中包含了验证吗? 答案是我们这样做了,但仅限于该组件内部的表单。 如果我们不实现接口,父表单将无法知道这个嵌套表单的状态。

由于这次我们没有注入 NgControl,我们还需要使用 NG_VALUE_ACCESSOR 令牌作为值访问器和使用 NG_VALIDATORS 令牌作为验证器来提供这个组件。

而已! 我们已经实现了一个表单组来收集用户的个人信息。 表单组是可重用的,并且可以嵌套在现有的反应式表单中。

结论

在本文中,我们研究了一些在处理 Angular 表单时让我们的生活更轻松的方法。 我们看到了如何创建与表单模块无关的自定义表单控件。 然后我们利用这些知识创建了一个可重用的嵌套表单组,该表单组由多个输入字段组成。

搜索更多有关“ Angular如何进行列表排序”的信息 [百度搜索] [SoGou搜索] [头条搜索] [360搜索]
CopyRight © 2008-2024 ManBetXappAll Rights Reserved. 手机版