es 过滤后排序排序_如何升级角度排序过滤器

es 过滤后排序排序

介绍 (Introduction)

AngularJS, One of the most useful features of AngularJS’s initial offering was the ability to filter and sort data on the page using only template variables and filters. Two-way data binding won over many converts to AngularJS.

AngularJS最初提供的最有用的功能之一是能够仅使用模板变量和过滤器对页面上的数据进行过滤和排序。 双向数据绑定赢得了许多到AngularJS的转换。

Today, though, many front-end developers prefer one-way data binding, and those orderBy and filter filters have been sunset with the advent of Angular. (Note: throughout this article I’ll be using “AngularJS” to refer to 1.x and just “Angular” to refer to 2+.)

但是,如今,许多前端开发人员更喜欢单向数据绑定,随着Angular的出现,那些orderByfilter器已不复存在。 (注意:在本文全文中,我将使用“ AngularJS”来指代1.x,而仅使用“ Angular”来指代2+。)

But how are we supposed to achieve that same effect? The answer lies in our components, so let’s look at an ngUpgrade project and learn how to do this!

但是我们应该如何达到同样的效果呢? 答案在于我们的组件,因此让我们看一个ngUpgrade项目并学习如何做!

步骤1 —从Git提取代码 (Step 1 — Pull Code from Git)

We’re going to step through updating the template of a freshly rewritten component. Then, we’ll add sorting and filtering to restore all of the functionality it had in AngularJS. This is a key skill to develop for the ngUpgrade process.

我们将逐步更新新编写的组件的模板。 然后,我们将添加排序和过滤以恢复它在AngularJS中具有的所有功能。 这是为ngUpgrade流程开发的一项关键技能。

To get started, take a moment to clone the sample project we’ll be using (don’t forget to run npm install in both the public and server folders). Check out this commit for our starting point:

要开始,花一点时间来克隆,我们将使用(不要忘了运行示例项目npm install在两个publicserver文件夹)。 查看此提交作为我们的起点:

git checkout 9daf9ab1e21dc5b20d15330e202f158b4c065bc3

This sample project is an ngUpgrade hybrid project that uses both AngularJS 1.6 and Angular 4. It’s got a working Express API and a Webpack builds for both development and production. Feel free to explore, fork it, and use the patterns in your own projects. If you’d like to look at a version of this project that uses Angular 5, check out this repo. For the purposes of this tutorial, the differences between the two versions won’t matter (I’ll point out anything minor).

该示例项目是一个使用AngularJS 1.6和Angular 4的ngUpgrade混合项目。它具有有效的Express API和用于开发和生产的Webpack构建。 随意探索,使用它并在您自己的项目中使用这些模式。 如果您想查看使用Angular 5的该项目的版本,请查看此repo 。 就本教程而言,两个版本之间的差异无关紧要(我会指出一些次要问题)。

第2步-替换AngularJS语法 (Step 2 — Replace the AngularJS Syntax)

At this stage in our application, our orders component is rewritten in Angular, with all of its dependencies injected and resolved. If we were to try to run our application, though, we’d see errors in the console indicating problems with our template. That’s what we need to fix first. We’re going to replace the AngularJS syntax in the orders template (orders/orders.html) so we can get the route loading and the orders displayed on the page. We’ll fix the filtering and sorting next.

在应用程序的此阶段,我们的订单组件将用Angular重写,并注入并解析所有依赖项。 但是,如果尝试运行应用程序,则会在控制台中看到错误,表明模板存在问题。 这就是我们首先需要解决的问题。 我们将替换订单模板( orders/orders.html )中的AngularJS语法,以便获取路线加载和页面上显示的订单。 接下来,我们将解决过滤和排序问题。

The first thing we need to do is get rid of all of the instances of $ctrl in this template. They’re no longer necessary in Angular. We can just do a find and replace to find for $ctrl. (note the dot), and replace it with nothing.

我们需要做的第一件事是摆脱此模板中$ctrl的所有实例。 在Angular中不再需要它们。 我们可以进行查找并替换以查找$ctrl. (请注意圆点),然后将其替换为任何内容。

Now let’s replace the data-ng-click in our button on line 13. In Angular, instead of ng-click, we just use the click event, with parentheses to indicate that it’s an event. Brackets indicate an input, and parentheses indicate an output or an event.

现在,让我们替换第13行中的按钮中的data-ng-click 。在Angular中,我们仅使用click事件,而不是ng-click ,并用括号将其表示为事件。 方括号表示输入,括号表示输出或事件。

<button type="button" (click)="goToCreateOrder()" class="btn btn-info">Create Order</button>

We’re just saying here that on the click event, fire off the goToCreateOrder function on our orders component.

我们在这里只是说,在click事件上,在订单组件上触发goToCreateOrder函数。

Before we keep going, let’s take a minute to prove that our component is actually loading. Comment out the whole div that loads our orders (from line 17 on). To run the application, open a terminal and run the following commands:

在继续之前,让我们花一点时间来证明我们的组件实际上正在加载。 注释掉加载我们订单的整个div (从第17行开始)。 要运行该应用程序,请打开一个终端并运行以下命令:

cd server
npm start

That will start the Express server. To run the Webpack dev server, open another terminal and run:

这将启动Express服务器。 要运行Webpack开发服务器,请打开另一个终端并运行:

cd public
npm run dev

(You can keep these processes running for the remainder of this tutorial.)

(您可以在本教程的其余部分中保持这些进程的运行。)

You should see that our application is loading again. If you go to the orders route, you’ll see that the orders component is displaying correctly.

您应该看到我们的应用程序正在重新加载。 如果转到订单路线,您会看到订单组件显示正确。

We can also click the Create Order button and it will send us correctly over to our Create Order route and form.

我们还可以单击“创建订单”按钮,它将正确地将我们发送到“创建订单”路线和表单。

Okay, let’s get back to the HTML. Un-comment that div (our app will be broken again).

好的,让我们回到HTML。 取消对该div的注释(我们的应用将再次损坏)。

Let’s replace all of the rest of the instances data-ng-click with the (click) event handler. You can either use Find & Replace or just use your editor’s shortcut for selecting all occurrences (in VS Code for Windows, this is Ctrl+Shift+L).

让我们用(click)事件处理程序替换所有其余实例data-ng-click 。 您可以使用“查找并替换”,也可以只使用编辑器的快捷方式来选择所有出现的对象(在Windows的VS Code中,这是Ctrl + Shift + L)。

Next, replace all of the occurrences of data-ng-show with *ngIf. There’s actually no direct equivalent to ng-show in Angular, but that’s okay. It’s preferable to use *ngIf, because that way you’re actually adding and removing elements from the DOM instead of just hiding and showing them. So, all we need to do is find our data-ng-shows and replace with *ngIf.

接下来,将所有出现的data-ng-show替换为*ngIf 。 实际上在Angular中没有直接等效于ng-show的方法,但这没关系。 最好使用*ngIf ,因为那样您实际上是在DOM中添加和删除元素,而不仅仅是隐藏和显示它们。 因此,我们所需要做的就是找到我们的data-ng-show并替换为*ngIf

Finally, we need to do two things to fix our table body. First, replace data-ng-repeat with *ngFor="let order of orders". Note that we’re also removing the orderBy and filter filters in that line so that the entire tr looks like this:

最后,我们需要做两件事来固定桌子主体。 首先,将data-ng-repeat替换为*ngFor="let order of orders" 。 请注意,我们还删除了该行中的orderByfilter器,因此整个tr如下所示:

<tr *ngFor="let order of orders">

Second, we can delete the data-ng prefix before the href link to the order detail route. AngularJS is still handling the routing here, but we don’t need to use that prefix anymore since this is now an Angular template.

其次,我们可以删除href链接到订单详细信息路径之前的data-ng前缀。 AngularJS仍在此处处理路由,但是我们现在不再需要使用该前缀,因为它现在是Angular模板。

If we look at the application again, you can see that the orders are loading correctly on the screen:

如果我们再次查看该应用程序,您会在屏幕上看到订单正在正确加载:

There are a couple things wrong with it, of course. The sorting links no longer work, and now our currency is kind of messed up because the currency pipe in Angular is slightly different than its AngularJS counterpart. We’ll get to that. For now, this is a great sign, because it means that our data is getting to the component and loading on the page. So, we’ve got the basics of this template converted to Angular. Now we’re ready to tackle our sorting and filtering!

当然,有几处错误。 排序链接不再起作用,现在我们的货币有点混乱了,因为Angular中的货币管道与AngularJS中的货币管道略有不同。 我们将解决这个问题。 目前,这是一个好兆头,因为这意味着我们的数据正在到达组件并加载到页面上。 因此,我们已经将该模板的基础知识转换为Angular。 现在,我们准备解决我们的排序和过滤!

第3步-添加排序 (Step 3 — Adding Sorting)

We’ve got our orders loading on the screen, but we don’t have a way of ordering or sorting them yet. In AngularJS, it was really common to use the built-in orderBy filter to sort the data on the page. Angular no longer has an orderBy filter. This is because it’s now strongly encouraged to move that kind of business logic into the component instead of having it on the template. So, that’s what we’re going to do here. (Note: we’re going to be using plain old functions and events here, not a reactive form approach. This is because we’re just trying to take baby steps into understanding this stuff. Once you’ve got the basics down, feel free to take it further with observables!)

屏幕上已经加载了订单,但还没有订购或排序的方法。 在AngularJS中,通常使用内置的orderBy过滤器对页面上的数据进行排序。 Angular不再具有orderBy过滤器。 这是因为现在强烈建议将这种业务逻辑移入组件,而不是将其放在模板上。 因此,这就是我们在这里要做的。 (注意:我们将在这里使用简单的旧函数和事件,而不是被动形式的方法。这是因为我们只是试图采取一些简单的步骤来理解这些内容。一旦您掌握了基础知识,就可以可以自由地将其与可观察的事物进一步融合!)

在组件中排序 (Sorting in the Component)

We already removed the orderBy filter from ng-repeat when we changed it to *ngFor. Now we’re going to make a sorting function on the orders component. We can use the click events on our table headers to call that function and pass in the property that we want to sort by. We’re also going to have that function toggle back and forth between ascending and descending.

当我们将其更改为*ngFor时,已经从ng-repeat删除了orderBy过滤器。 现在,我们将对订单组件进行排序。 我们可以使用表头上的click事件来调用该函数,并传入要排序的属性。 我们还将使该功能在上升和下降之间来回切换。

Let’s open the orders component (./orders/orders.component.ts) and add two public properties to the class. These are going to match the two properties that our template already references. The first one will be sortType of type string. The second one will be sortReverse of type boolean and we’ll set the default value to false. The sortReverse property just keeps track of whether to flip the order - don’t think of it as a synonym for ascending or descending.

让我们打开订单组件( ./orders/orders.component.ts ),然后向该类添加两个公共属性。 这些将匹配模板已经引用的两个属性。 第一个将是sortType类型的string 。 第二个将是boolean类型的sortReverse ,我们将默认值设置为false。 sortReverse属性只是跟踪是否翻转顺序-不要将其视为升序或降序的同义词。

So you now should have this after the declaration of the title in the class:

因此,您现在应该在该类中的标题声明之后使用以下代码:

sortType: string;
sortReverse: boolean = false;

Next, we’ll add the function that we’ll use with the Array.sort prototype function in JavaScript. Add this after the goToCreateOrder function (but still within the class):

接下来,我们将添加与JavaScript中的Array.sort原型函数一起使用的函数。 将其添加到goToCreateOrder函数之后(但仍在类中):

dynamicSort(property) {
    return function (a, b) {
        let result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result;
    } 
}

This dynamic sort function will compare the property value of objects in an array. The nested ternary function can be a little bit tricky to understand at first glance, but it’s basically just saying that if the value of our property of A is less than B, return -1. Otherwise, if it’s greater, return 1. If the two are equal, return 0.

此动态排序功能将比较数组中对象的属性值。 嵌套三元函数乍一看可能有些棘手,但基本上只是说如果我们的A的属性值小于B,则返回-1。 否则,返回1。如果两者相等,则返回0。

Now, this isn’t super sophisticated or deep comparison. There are way more sophisticated helper functions you could write to sort for you, and feel free to experiment with how you can break this one. It will do for our purposes, though, and you can just swap out this logic with whatever custom sorting logic you like.

现在,这不是超级复杂或深入的比较。 您可以编写一些更复杂的帮助程序功能来为您排序,并随时尝试如何打破这一功能。 不过,它会为我们的目的而工作,您可以将此逻辑替换为您喜欢的任何自定义排序逻辑。

So that’s our helper function. The sort function on the Array prototype can be passed a function that it can then use to compare items in an array. Let’s make a function called sortOrders on our class that takes advantage of that with the new dynamicSort function:

这就是我们的辅助功能。 可以将Array原型上的sort函数传递给函数,然后可以使用该函数比较数组中的项目。 让我们在类上创建一个名为sortOrders的函数,通过新的dynamicSort函数利用该函数:

sortOrders(property) { }

The first thing we need to do is set the sortType property on our class equal to the property that’s passed in. Then we want to toggle the sortReverse property. We’ll have this:

我们需要做的第一件事是将类上的sortType属性设置为与sortType属性相等。然后,我们要切换sortReverse属性。 我们将有这个:

sortOrders(property) {
    this.sortType = property;
     this.sortReverse = !this.sortReverse;
}

Now we can call the sort function on this.orders, but pass in our dynamic sort function with our property:

现在我们可以在this.orders上调用sort函数,但是将我们的属性传递给我们的动态sort函数:

sortOrders(property) {
    this.sortType = property;
    this.sortReverse = !this.sortReverse;
    this.orders.sort(this.dynamicSort(property));
}

And there’s one last thing we need to do. We need to modify our dynamicSort function just a little bit to be able to reverse the order of the array for ascending or descending. To do this, we’ll tie the result of the dynamicSort to the sortReverse property on the class.

我们需要做的最后一件事。 我们只需要稍微修改dynamicSort函数就可以颠倒数组的升序或降序。 为此,我们将把dynamicSort的结果dynamicSort到类的sortReverse属性上。

The first thing we’ll do is declare a variable:

我们要做的第一件事是声明一个变量:

let sortOrder = -1;

let sortOrder = -1;

Then, we can check if our sortReverse property on our class is true or false. If it’s true, we’ll set our sort order variable equal to 1:

然后,我们可以检查类上的sortReverse属性是true还是false。 如果是真的,我们将排序顺序变量设置为等于1:

if (this.sortReverse) {
    sortOrder = 1;
 }

We’re tying our functions together like this because we’re doing a toggle in our sort function for the sake of demonstration. To be more thorough, another approach would be to have a variable called sortDescending instead of sortReverse that’s controlled through a separate function. If you go this route, you’ll do the opposite – sortOrder would be 1 unless sortDescending was true.

我们将函数绑定在一起是因为为了演示,我们在sort函数中进行了切换。 为了更全面,另一种方法是使用名为sortDescending的变量,而不是通过单独的函数控制的sortReverse 。 如果您走这条路线,您将执行相反的操作– sortOrder将为1,除非sortDescending为true。

We could also combine these last two things into a ternary expression, but for the sake of clarity, I’m going to leave it a little bit more verbose. And then to just make our result the opposite of what it normally would be, I can just multiply result by our sortOrder. So our dynamicSort function now looks like this:

我们也可以将最后两件事组合成一个三元表达式,但是为了清楚起见,我将使其更加冗长。 然后,为了使我们的结果与通常的结果相反,我可以将result乘以我们的sortOrder 。 因此,我们的dynamicSort函数现在如下所示:

dynamicSort(property) {
     let sortOrder = -1;

    if (this.sortReverse) {
        sortOrder = 1;
    }

    return function(a, b) {
        let result = a[property] < b[property] ? -1 : a[property] > b[property] ? 1 : 0;
         return result * sortOrder;
    };
  }

Again, this is a demonstration implementation of sorting, so that you understand the key concepts of using a custom sorting function on your component.

同样,这是排序的演示实现,因此您可以了解在组件上使用自定义排序功能的关键概念。

让我们看看排序是否有效 (Let’s see if the sort works)

So far, we’ve added a dynamicSort helper function and a sortOrders function to our class so that we can sort on our component instead of on our template.

到目前为止,我们已经在类中添加了dynamicSort辅助函数和sortOrders函数,以便我们可以对组件进行排序而不是对模板进行排序。

To see if these functions are working, let’s add a default sorting to our ngOnInit function.

要查看这些功能是否正常工作,让我们向ngOnInit函数添加默认排序。

Inside of our forkJoin subscription, after the forEach where we add the customer name property, let’s call this.sortOrders and pass in the total items property:

forkJoin订阅中,在forEach之后添加客户名称属性,让我们调用this.sortOrders并传入total items属性:

this.sortOrders('totalItems');

this.sortOrders('totalItems');

When the screen refreshes, you should see that the orders are being sorted by the total items.

屏幕刷新时,您应该看到订单正在按总项目排序。

Now we just need to implement this sorting on our template by calling the sortOrders function in the from the table header links.

现在,我们只需要在表头链接中通过调用sortOrders函数对模板进行排序。

将排序添加到模板 (Add sorting to the template)

We’ve got our sortOrders function working correctly on our orders component, which means we’re now ready to add it to our template so that the table headers are clickable again.

我们已经使sortOrders函数在orders组件上正常工作,这意味着我们现在可以将其添加到模板中,以便再次单击表头。

Before we do that, let’s change the default sorting in our ngOnInit function to just be ID:

在此之前,让我们将ngOnInit函数中的默认排序更改为ID:

this.sortOrders('id');

this.sortOrders('id');

That’s a little bit more normal than using the total items.

这比使用总计项目要正常一些。

Now we can work on our template. The first thing we want to do is call the sortOrders function in all of our click events. You can select the instances of sortType = and replace them with sortOrders(. Then, you can replace the instances of ; sortReverse = !sortReverse with ).

现在我们可以处理我们的模板了。 我们要做的第一件事是在所有单击事件中调用sortOrders函数。 您可以选择sortType =的实例并用sortOrders( 。替换它们;然后,可以将; sortReverse = !sortReverse的实例替换为)

We also need to fix two of the property names that we’re passing in here, as well as in the *ngIf instances. Replace the 3 instances of orderId with id and the 3 instances of customername with customerName.

我们还需要修复在此以及*ngIf实例中传递的两个属性名称。 将3个orderId实例替换为id ,并将3个customername实例替换为customerName

The last thing I need to do is wrap each of the href tags in the headers in brackets so that Angular will take over and these links won’t actually go anywhere. The click event will be the thing that’s fired. So, the headers should follow this pattern:

我需要做的最后一件事是将每个href标记包装在标题的方括号中,以便Angular接管,并且这些链接实际上不会到任何地方。 点击事件将被触发。 因此,标头应遵循以下模式:

<th>
    <a [href]="" (click)="sortOrders('id')">
        Order Id
        <span *ngIf="sortType == 'id' && !sortReverse" class="fa fa-caret-down"></span>
        <span *ngIf="sortType == 'id' && sortReverse" class="fa fa-caret-up"></span>
         </a>
</th>

Hop over to the browser and test out all of your table header links. You should see that each one of our properties now sorts, both in ascending and descending order. Awesome!

跳到浏览器并测试所有表头链接。 您应该看到我们的每个属性现在都按升序和降序排序。 太棒了!

This is great, but we did lose one thing - our cursor is a selector, not a pointer. Let’s fix that with some CSS.

很好,但是我们确实失去了一件事-光标是选择器,而不是指针。 让我们用一些CSS修复它。

修复光标 (Fix the Cursor)

We’ve got our sorting working correctly on our orders page, but our cursor is now a selector instead of a pointer, and that’s annoying.

我们的订单页面上的排序工作正常,但是光标现在是选择器而不是指针,这很烦人。

There are a couple of different ways we could use CSS to fix this:

我们可以使用几种不同的方法来使用CSS来解决此问题:

  • We could make a class in our main app SCSS file.

    我们可以在主应用程序SCSS文件中创建一个类。
  • We could write in-line CSS, although that’s almost never preferable.

    我们可以编写内联CSS,尽管这几乎从来都不是可取的。
  • We could take advantage of Angular’s scoped CSS using the styles option in the component decorator

    我们可以使用组件装饰器中的styles选项来利用Angular的作用域CSS

We’re going to go with the last option, because all we need to do is add one rule to our styles for this particular component.

我们将使用最后一个选项,因为我们要做的就是为该特定组件的样式添加一条规则。

Open up the orders component class again. In the component decorator, we can add a new property called styles. Styles is an array of strings, but the strings are CSS rules. To fix our cursor, all we need to do is write out a rule that says that in a table row, if we have a link, then change the cursor property to pointer. Our decorator will now look like this:

再次打开订单组件类。 在组件装饰器中,我们可以添加一个称为styles的新属性。 样式是字符串数组,但是字符串是CSS规则。 要修复游标,我们所需要做的就是写出一条规则,该规则说在表行中,如果有链接,则将cursor属性更改为pointer。 现在,我们的装饰器将如下所示:

@Component({
    selector: 'orders',
    template: template,
    styles: ['tr a { cursor: pointer; }']
})

Now, when we hover over our row headers, you see we have the pointer cursor. What’s cool about this approach is that this CSS rule won’t affect any other components. It will just apply to our orders component!

现在,当我们将鼠标悬停在行标题上时,您将看到指针光标。 这种方法的妙处在于该CSS规则不会影响任何其他组件。 它将仅适用于我们的订单组件!

Now, let’s see if we can do something about our filtering. That “filter filter” was removed from Angular, so we’re going to have to be creative and come up with a way to implement it on our component.

现在,让我们看看是否可以对过滤进行一些处理。 该“过滤器过滤器”已从Angular中删除,因此我们将必须具有创造力,并提出一种在组件上实施该过滤器的方法。

步骤4 —添加过滤 (Step 4 — Add Filtering)

We’re ready to replace our filter box that used to use the AngularJS filter to search through orders collection based on a string that we were searching. The AngularJS filter lived on our template and didn’t require any code in our controller or component. Nowadays, that kind of logic in the template is discouraged. It’s preferred to do that kind of sorting and filtering on our component class.

我们已经准备好替换以前用来使用AngularJS过滤器来搜索基于所搜索字符串的订单集合的过滤器框。 AngularJS过滤器位于我们的模板上,并且在控制器或组件中不需要任何代码。 如今,不鼓励在模板中使用这种逻辑。 最好对我们的组件类进行这种排序和过滤。

添加过滤器功能 (Add a Filter Function)

Back in our component, we’re going to make a new array of orders called filteredOrders. Then we’re going to pass our orders array into a filter function that sets the filteredOrders array. Finally, we’ll use the filteredOrders on our template in our *ngFor instead of our original array. That way we’re not ever modifying the data that comes back from the server, we’re just using a subset of it.

回到我们的组件中,我们将创建一个新的订单数组,称为filteredOrders 。 然后,我们将orders数组传递给一个用于设置filteredOrders数组的filteredOrders器函数。 最后,我们将在模板中的*ngFor而不是原始数组中使用filteredOrders 。 这样,我们就永远不会修改从服务器返回的数据,而只是使用其中的一部分。

The first thing we’ll do is declare the new property on our class :

我们要做的第一件事是在类上声明新属性:

filteredOrders: Order[];

Then, in our forkJoin that sets our original array of orders, we can set the initial state of filteredOrders to our orders array:

然后,在设置原始订单数组的forkJoin中,我们可以将filteredOrders的初始状态设置为我们的订单数组:

this.filteredOrders = this.orders;

this.filteredOrders = this.orders;

Now we’re ready to add our function that will actually do the filtering for us. Paste this function in right after our sorting functions at bottom of our component:

现在,我们准备添加将实际为我们进行过滤的函数。 将此功能粘贴到组件底部的排序功能之后:

filterOrders(search: string) {
    this.filteredOrders = this.orders.filter(o =>
      Object.keys(o).some(k => {
        if (typeof o[k] === 'string')
          return o[k].toLowerCase().includes(search.toLowerCase());
      })
    );
  }

Let’s talk about what’s going on in this function. First, we’re giving the function a string property of search. Then, we loop through our orders and then find all of the keys of the objects. For all of the keys, we’re going to see if there are some values of those properties that match our search term. This bit of JavaScript can look a little confusing at first, but that’s basically what’s going on.

让我们谈谈此函数的功能。 首先,我们为该函数提供search的字符串属性。 然后,我们遍历订单,然后找到对象的所有键。 对于所有的钥匙,我们要看看是否有some那些符合我们的搜索词属性的值。 刚开始时,这种JavaScript有点令人困惑,但是基本上就是这样。

Note that, in our if statement, we’re explicitly testing for strings. In our example right now we’re just going to limit our query to strings. We’re not going to try to deal with nested properties, number properties, or anything like that. Our search term will match on our customer name property, and if we ever choose to display our address or any other string property it’ll search through those as well.

请注意,在我们的if语句中,我们正在显式测试字符串。 现在在我们的示例中,我们仅将查询限制为字符串。 我们不会尝试处理嵌套属性,数字属性或类似的东西。 我们的搜索字词将与我们的客户名属性匹配,并且如果我们选择显示地址或任何其他字符串属性,它也会搜索这些内容。

Of course, we could also modify this function to test for numbers, or look through another layer of nested objects, and that’s totally up to you. Just like with our sorting, we’re going to start with a demonstration implementation and let you use your imagination to make it more complex.

当然,我们也可以修改此功能以测试数字,或查看另一层嵌套对象,这完全取决于您。 就像我们的排序一样,我们将从演示实现开始,让您利用自己的想象力使其变得更复杂。

Speaking of the sortOrders function, before we move on, we need to do one last thing on the component. We just need to modify sortOrders to use filteredOrders now and not our original orders, because we want the filter to take priority over the sorting. Just change it to this:

说到sortOrders函数,在继续之前,我们需要对组件做最后一件事。 我们只需要修改sortOrders即可立即使用filteredOrders而不是原始orders ,因为我们希望过滤器优先于排序。 只需将其更改为:

sortOrders(property) {
    this.sortType = property;
    this.sortReverse = !this.sortReverse;
    this.filteredOrders.sort(this.dynamicSort(property));
}

Now we’re ready to implement this filtering on the template.

现在,我们准备在模板上实现此过滤。

将过滤添加到模板 (Add Filtering to the Template)

Let’s move back to our template and fix it up to use our filtering.

让我们回到模板并对其进行修复以使用我们的过滤。

The first thing we need to do is replace data-ng-model. Instead of that, we’re going to use the keyup event, so we’ll write, “keyup” and surround it parentheses ((keyup)). This is a built-in event in Angular that lets us run a function on the key up of an input. Since we named our function filterOrders, which used to be the name of the property that we were passing into the AngularJS filter, we just need to add parentheses next to it. Our input looks like this so far:

我们需要做的第一件事是替换data-ng-model 。 取而代之的是,我们将使用keyup事件,因此我们将编写“ keyup”并将其括在括号中( (keyup) )。 这是Angular中的内置事件,使我们可以在输入的键上运行函数。 由于我们将函数命名为filterOrders ,该函数曾经是要传递到AngularJS过滤器中的属性的名称,因此我们只需要在其旁边添加括号即可。 到目前为止,我们的输入看起来像这样:

<input type="text" class="form-control" placeholder="Filter Orders (keyup)="filterOrders()">

But what do we pass into the filter orders function? Well, by default, events pass something called $event. This contains something called a target, which then contains the value of the input. There’s one problem with using $event. It’s very difficult to keep track of those nebulous types because target.value could really be anything. This makes it tough to debug or know what type of value is expected. Instead, Angular has a really nifty thing we can do, which is to assign a template variable to this input.

但是,我们要传递给过滤器订单功能什么呢? 好吧,默认情况下,事件传递一个称为$event东西。 它包含一个叫做target东西,然后包含输入的值。 使用$event有一个问题。 跟踪那些模糊的类型非常困难,因为target.value确实可以是任何东西。 这使得调试或知道期望值的类型变得困难。 相反,Angular有一件我们可以做的很漂亮的事情,就是为该输入分配一个模板变量

Luckily, Angular provides a method for us to do this. After our input tag, we can add the hash sign (#) and then the name of our desired model. Let’s call it #ordersFilter. It really doesn’t matter where in the tag you put this or what you call it, but I like to put it after the input so that you catch which model is associated with which input if I just glance down the page.

幸运的是,Angular为我们提供了一种方法。 在输入标签之后,我们可以添加井号(#),然后添加所需模型的名称。 我们称之为#ordersFilter 。 将该标签放置在标签中的什么位置或名称实际上并不重要,但是我喜欢将其放置在输入之后,以便您浏览一下页面即可捕获与哪个模型关联的输入。

Now I can pass that variable into our filterOrders function on the keyup event. We don’t need the hash symbol before it, but we do need to add .value. This will pass the actual value of the model and not the entire model itself. Our finished input looks like this:

现在,我可以在keyup事件中将该变量传递到我们的filterOrders函数中。 我们不需要在其前面的哈希符号,但是我们确实需要添加.value 。 这将传递模型的实际值,而不是整个模型本身。 我们完成的输入如下所示:

<input #ordersFilter type="text" class="form-control" 
    placeholder="Filter Orders" (keyup)="filterOrders(ordersFilter.value)">

Finally, we need to modify our *ngFor to use the filteredOrders array instead of the regular orders array:

最后,我们需要修改*ngFor以使用filteredOrders数组而不是常规的orders数组:

<tr *ngFor="let order of filteredOrders">

检查产品 ( Inspect the Product)

You can see how much cleaner our template is now that our filtering and sorting is in the component.

您现在可以看到组件中的过滤和排序功能使模板更加干净。

Now let’s check this out in the browser. If you enter some text in the box, like “sally,” you should see that our orders are changing and that the sorting works on top of it:

Animation of working app Awesome, we’ve replaced another AngularJS feature!

现在,让我们在浏览器中检查一下。 如果您在框中输入一些文字(例如“ sally”),则应该看到我们的订单正在更改,并且排序在其上面进行:

Now we’ve just got one last thing we need to do on this component - fix the currency pipe.

现在,我们需要在此组件上做的最后一件事-修复货币管道。

步骤5 —修复货币管道 (Step 5 — Fix the Currency Pipe)

Our final touch is to update the former currency filter, which is now called the currency pipe in Angular. We just need to add a couple of parameters to the pipe in the template that we didn’t have to specify in AngularJS. This part differs if you’re using Angular 4 or Angular 5:.

我们的最后一步是更新以前的货币过滤器,现在将其称为Angular中的货币管道 。 我们只需要在模板中的管道中添加几个参数,而不必在AngularJS中指定。 如果您使用的是Angular 4或Angular 5,则此部分有所不同。

In Angular 4, do this: <td>{{order.totalSale | currency:'USD':true}}</td>

在Angular 4中,执行以下操作: <td>{{order.totalSale | currency:'USD':true}}</td> <td>{{order.totalSale | currency:'USD':true}}</td>

In Angular 5+, do this: <td>{{order.totalSale | currency:'USD':'symbol'}}</td>

在Angular 5+中,执行以下操作: <td>{{order.totalSale | currency:'USD':'symbol'}}</td> <td>{{order.totalSale | currency:'USD':'symbol'}}</td>

The first option is the currency code (there’s lots, you’re not limited to US dollars!). The second one is the symbol display. In Angular 4, this is a boolean that indicates whether to use the currency symbol or the code. In Angular 5+, the options are symbol, code, or symbol-narrow as strings.

第一种选择是货币代码(有很多,您不仅限于美元!)。 第二个是符号显示。 在Angular 4中,这是一个布尔值,指示是使用货币符号还是使用代码。 在Angular 5+中,选项是symbolcodesymbol-narrow作为字符串。

You should now see the expected symbol:

Screenshot of Total Sale column of app

现在,您应该看到预期的符号:

And we’re done! To see the finished code, check out this commit.

我们完成了! 要查看完成的代码, 请签出此commit

结论 (Conclusion)

You did a great job sticking with this to the end! Here’s what we’ve accomplished in this guide:

坚持到底,您做得很棒! 这是本指南中完成的工作:

  1. Replacing AngularJS template syntax with Angular syntax

    用Angular语法替换AngularJS模板语法
  2. Moving sorting to the component

    将排序移至组件
  3. Using scoped CSS styles

    使用范围CSS样式
  4. Moving filtering to the component

    将过滤移至组件
  5. Replacing the AngularJS currency filter with the Angular currency pipe

    用Angular货币管道替换AngularJS货币过滤器

Where should you go from here? There are lots of things you could do:

你应该从这里去哪里? 您可以做很多事情:

  • Make the sorting more sophisticated (for example: should the ordering reset or stay the same when the user clicks a new header?)

    使排序更加复杂(例如:当用户单击新标题时,排序应该重置还是保持不变?)
  • Make the filtering more sophisticated (search for numbers or nested properties)

    使过滤更加复杂(搜索数字或嵌套属性)
  • Change to a reactive approach. You could listen to an observable of value changes instead of the keyup function and do sorting and filtering in there. Using observables would also let you do really cool things like debounce the input!

    更改为被动方法。 您可以监听可观察到的值变化,而不是keyup函数,然后在其中进行排序和过滤。 使用可观察变量还可以使您做一些非常酷的事情,例如对输入进行去抖动!

翻译自: https://www.digitalocean.com/community/tutorials/how-to-upgrade-angular-sorting-filters

es 过滤后排序排序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值