AngularJS. Сортировка данных в AngularJS. Фильтр orderBy. Часть 1


AngularJS: пользовательская функция сортировки с помощью OrderBy

Я пытаюсь определить свою собственную функцию сортировки, используя документацию, представленную в http://docs.angularjs.org/api/ng.filter:orderBy.

Прежде чем я объясню написанный код, я также упомянул о поведении, которое я ожидаю. У меня есть таблица, которая содержит заголовок таблицы (th) и данные таблицы (td). Когда пользователь нажимает на столбец в таблице (по столбцу, я имею в виду th), данные таблицы должны сортироваться на основе значения в этом столбце.

Если пользователь снова нажмет один и тот же столбец, сортировка изменится на восходящий/нисходящий, если предыдущие критерии сортировки снижались/восходящие соответственно.
Пользователь может сортировать несколько столбцов. Первый выбранный столбец дает первый приоритет. Если первое значение столбца совпадает, тогда используется второй столбец, выбранный для сортировки.

Теперь для кода. Его можно найти здесь: http://jsfiddle.net/xkjmv/

Проблема в том, что customSortFunction возвращает массив, как ожидалось, но сортировка не работает — когда пользователь нажимает на заголовок столбца, сортировка должна быть либо восходящей, либо нисходящей (в основном переключаться при каждом нажатии).

Я хочу вернуть массив предикатов строк, так как у меня будет несколько столбцов для сортировки, но одна сортировка столбца с использованием самого предиката строки не работает

EDIT: вы можете проверить консоль, чтобы увидеть результат, который возвращает пользовательская функция сортировки, если это не очевидно из кода.

Не работает сортировка (orderBy)

Тема не актуальная. Ошибку нашёл. В топку это сообщение.

Добавил сортировку «orderBy:sortType:sortReverse». Не работает.
Ставил напрямую «orderBy:’name’ «, бесполезно.

Вроде код написан правильно, в чём причина непонятно.

Добавлено через 6 минут
$scope.sortType = ‘text’;

Тема не актуальная.

In Angular 5+, do this:

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.

You should now see the expected symbol:

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

Where to Go From Here

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

  1. Replacing AngularJS template syntax with Angular syntax
  2. Moving sorting to the component
  3. Using scoped CSS styles
  4. Moving filtering to the component
  5. Replacing the AngularJS currency filter with the Angular currency pipe

Wow! That’s a lot — you should feel super proud!

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!

![](https://cdn.scotch.io/1/VPlsSVxRQGCXrq4cnQtA_0EZmP93.png)

If you love this guide, I’ve got 200+ detailed videos, quiz questions, and more for you in my comprehensive course Upgrading AngularJS. I created it for everyday, normal developers and it’s the best ngUpgrade resource on the planet. Head on over and sign up for our email list to get yourself a free Upgrade Roadmap Checklist so you don’t lose track of your upgrade prep. And, while you’re there, check out our full demo.

Изучаем AngularJS на пяти практических примерах

Скачать рабочие материалы к данной статье


Вы, наверное, слышали уже о AngularJS – JS-фреймворке с открытым исходным кодом, разработанном специалистами Google, который реально меняет представление о веб-приложениях. О нем уже много было написано, но до сих пор в Сети очень трудно найти что-то действительно ориентированное на разработчиков.

Где бы лаконично и конкретно, на практических примерах были описаны принципы работы AngularJS. Цель этой статьи – изменить подобное положение вещей. Ниже приводится описание основных составляющих элементов Angular: Модели,Представления, Контроллеры, Сервисы и Фильтры, созданное на основе пяти конкретных примеров.

Если вы предпочитаете редактировать код через ваш любимый редактор, скачайте ZIP-архив по ссылке выше.

Что такое AngularJS?

По большому счету AngularJS является основой, которая связывает HTML-код (который генерируется для просмотра страницы в окне браузера) с JavaScript объектов /моделей. Когда изменяется один из объектов, автоматически обновляется и генерируемая страница. Верно и обратное — модели связаны с текстовым полем (контентом страницы). Когда изменяется контент, это вызывает изменения и в коде сайта.

AngularJS связывает коды в единую систему, и вам не нужно больше обновлять HTML вручную или инспектировать элементы, как в случае, если вы используете JQuery. В самом деле, ни в одном из примеров, приведенных здесь, даже не упоминается JQuery!

Для использования AngularJS вы должны добавить его в код своей страницы. Для этого в тэг нужно прописать соответствующие параметры. Google’s CDN для более быстрой загрузки рекомендую еще такой код:

AngularJS включает в себя большое количество директив , которые позволяют связать HTML-элементы моделей. Они представляют из себя атрибуты, начинающиеся с префикса ng-, их можно добавлять к любому элементу. Самым важным атрибутом, который, если вы хотите использовать Angular, нужно включить во все страницы сайта является ng- приложений:

Атрибут следует добавлять к элементу, который охватывает нужную нам часть страницы: либо все тело страницы, либо ее часть ограниченную тэгами div. Angular ищет его при загрузке страницы и автоматически оценивает все директивы , которые видит, как дочерние элементы.

Но довольно теории. Давайте рассмотрим непосредственно некоторые коды.

Меню навигации

В качестве первого примера мы создадим меню навигации, в котором выделяется активный элемент. В примере задействованы только директивы AngularJS, это самое простейшее приложение, использующее фреймворк.
Код выглядит следующим образом:

В приведенном выше примере, используются директивы Angular для задания и считывания активной переменной. Когда она изменяется, это инициирует изменения HTML-кода элемента. В терминологии Angular эта переменная называется моделью. Она доступна для всех директив текущей области. Ее также могут обрабатывать контроллеры (подробнее об этом в следующем примере).

Если вы использовали шаблоны JavaScript раньше, то вы знакомы с синтаксисом команды <>. Когда фреймворк видит такую строку, он заменяет содержимое переменной. Эта операция повторяется каждый раз, когда изменяется переменная.

Встроенный редактор

Для второго примера, мы создадим простой встроенный редактор – при нажатии пункта меню всплывает небольшое текстовое поле с подсказкой. Мы используем контроллер, который будет инициализировать модели и задавать два разных метода отображения подсказки. Контроллеры являются стандартными функциями JavaScript, которые автоматически выполняются фреймворком Angular. Они связаны с кодом отображения страницы вашего сайта через директивы ng-controller .

Когда функция контроллера запускается на исполнение, для нее в качестве параметра задается специальный объект $scope. Он отвечает за ввод текста в текстовый редактор. Для того, чтобы вывести его на экран, нужно прописать дополнительные свойства и функции, которые описывают отображение его элементов. С помощью NG-моделей осуществляется связь кода сайта с текстом, который вводится в рабочее поле редактора. При вводе текста Angular задает соответствующие изменения переменных.

Форма заказа

В этом примере мы рассмотрим код формы заказы, в которой автоматически выводится общая сумма. Здесь использована еще одна полезная функция AngularJS — фильтры . Фильтры позволяют вносить изменения в модели, а также объединять их с помощью символа «|». В приведенном ниже примере, используется фильтр валюты , чтобы перевести числовое значение в корректный формат цены — с разделением долларов и центов. Когда вы рассмотрите пример № 4, вы сможете с легкостью задавать свои собственные фильтры.

Связка ng-repeat ( описание ) – это еще один полезный элемент Angular. Она позволяет запустить цикл обработки массива элементов, а также задать разметку для каждого из них. Она автоматически обновляет код, если один из элементов был изменен или удален.

Функция поиска

В этом примере приводится функция, позволяющая фильтровать список элементов по определенному критерию. Это еще одно направление, где с успехом может применяться AngularJS.

Фреймворк является идеальным инструментом для создания пользовательских фильтров. Для этого сперва мы должны сформировать специальный модуль для нашего приложения.

Модули представляют собой форму организации приложений JavaScript в автономные компоненты, которые можно связывать между собою в разных вариантах и последовательностях. Angular также использует этот метод группировки кодов. Потому прежде, чем создавать фильтр, нужно сначала создать модули для разных приложений.

Для того, чтобы создать модуль приложения, нужно выполнить всего два действия:

  1. Использовать функцию angular.module(«name»,[]) при вызове JS. Это установит границы нового модуля;
  2. Задать имя модуля в качестве значения директивы ng-app.

После этого фильтр создается очень просто функцией filter(). Также просто потом вызвать его через обращение к соответствующему модулю angular.module(«name», []).

В создании различных фильтров используется подход, базирующийся на общей философии AngularJS. В соответствии с ней каждая часть кода, который вы пишете, должна быть автономной, легко тестируемой, а также иметь возможность использоваться разными элементами фреймворка. Вы можете применять созданный однажды фильтр для обработки данных в рамках других приложений. И даже объединять его в последовательности с другими фильтрами.

Функция переключения режима вывода элементов на странице

Еще одна популярная функция – переключение по выбору пользователя различных режимов вывода элементов на странице (список или плитка). Через Angular это делается очень просто.

Кроме того, в этом примере описывается еще один важный элемент фреймворка – сервисы. Это объекты, которые могут быть использованы приложениями для взаимодействия с сервером, API или другими источниками данных. В нашем случае, мы напишем сервис, который взаимодействует с Instagram’s API и выводит массив с самыми популярными на текущий момент фотографиями.

Обратите внимание, что для работы этого кода, нам потребуется использовать на странице дополнительный файл Angular.js:

Для оптимизации работы с AJAX API здесь используется модуль ngResource (в коде модуля задействована переменная $resource).

Сервисы – это полностью автономные элементы, что делает возможным написание различных вариантов модулей для реализации процесса, при этом не затрагивая остальную часть кода.

Например, во время тестирования, вы можете предпочесть выводить данные из четко заданного массива фотографий (без фильтров и обработки), что ускорит отладку всей системы.

Дополнительная литература

Если вы все же добрались до конца этой статьи, то у вас уже должно сложиться общее представление о базовых принципах работы с фреймворком AngularJS. Тем не менее, если вы хотите стать настоящим профи в данном вопросе, есть много источников, по которым вы можете изучить эту тему глубже. Вот список ресурсов, которые помогут вам этом:

Сайт AngularJS
Руководство по AngularJS
Официальное пособие по AngularJS
Список сайтов, где представлено еще много информации по теме, видео и учебники

Данная публикация представляет собой перевод статьи « Learn AngularJS With These 5 Practical Examples » , подготовленной дружной командой проекта Интернет-технологии.ру

Как отсортировать объектный источник данных в ng-repeat в AngularJS?

Предположим, у меня есть следующие пользователи:

Я хотел бы создать со следующими параметрами:

Другими словами, пользователи должны быть отсортированы по имени.

Я попробовал следующее с помощью (key, value) in expression , но он не работает:

Что мне не хватает?

Пожалуйста, не предлагайте решения с ng-options , поскольку я использую ui-select2 , который несовместим с ng-options

3 ответа

В то время как вы увидите это в ветке ссылок автора на ссылку, я подумал, что было бы неплохо предложить один из упомянутых обходных путей для SO:

Это правда, что это технически не реализовано, но есть простой способ обойти, если вы хотите немного изменить свою модель данных: использовать пользовательский фильтр для генерации массива свойств объекта ( без замена). Если вы добавите ключевое поле к объектам («id» в приведенном выше случае), вы сможете получить поведение, которое ищете:

Вот директива ng-repeat, которую можно использовать:

Обратите внимание, что фильтр orderBy принимает name в качестве параметра, а не user.name .

К сожалению, добавление свойства id к вашим объектам может привести к несоответствию его ключа в содержащем объекте.

В ссылке, которую вы упомянули в своем ответе, также есть предлагаемые решения, которые создают свойство id в пользовательских объектах на лету. , но я чувствую, что этот подход немного менее грязный (за счет внедрения репликации данных).

Топ-пост этого месяца:  Плагин для Google Chrome PerfectPixel
Добавить комментарий
Javascript
09.03.2020, 19:40

Не работает orderBy после изменения атрибута элемента
Здравствуйте! У меня есть коллекция элементов, у которых есть статус. Статус меняется так: -.

Двойная сортировка OrderBy
Ребят подскажите пожалуйста как сортировать данные по двум критериям с помощью OrderBy. Просто в.

Сортировка массива используя OrderBy
Можно-ли с помощью OrderBy сортировать массив так 1) все четный эллементы по возрастанию 2) все.

Сортировка последовательности с помощью OrderBy
Есть сгенерированная последовательность: int A = new int < 22, 62, 3, 7>; int B = new.

Orderby сортировка по дате и по алфавиту
Не сортируются вообще нечего можете поправить что не так пожалуйста view- @using.

AngularJS фильтры

Фильтры могут быть добавлены в AngularJS для форматирования данных.

AngularJS фильтры

AngularJS предоставляет фильтры для преобразования данных:

  • currency Формат числа в формате валюты.
  • date Формат даты в заданном формате.
  • filter выбора подмножества элементов из массива.
  • json Форматирование объекта в строку JSON.
  • limitTo Ограничивает массив / строку, в заданное число элементов / символов.
  • в lowercase формата строка в нижний регистр.
  • number Форматирование числа в строку.
  • orderBy Велит массив выражением.
  • uppercase Форматирование строки в верхний регистр.

Добавление фильтров в выражения

Фильтры могут быть добавлены к выражениям, используя символ вертикальной черты | , а затем с помощью фильтра.

В uppercase строки формата фильтра к верхнему регистру:

пример

В lowercase строки формата фильтра в нижнем регистре:

angularjs-orderby

На этот вопрос уже есть ответ здесь: orderBy несколько полей в угловой 7 ответов ——- Отредактированный вопрос —— Мне нужно…

вероятно, очень nooby вопрос, и я упускаю очевидное, но я использую функцию для сортировки результатов. Каждый результат имеет цену и…

Может ли кто-нибудь указать мне в правильном направлении, чтобы найти способ исправить то, как пейджинг и orderBy работают вместе в…

Я пытаюсь использовать ng-repeat с синтаксисом стиля словаря и применить порядок к значению ключа. (key, value) in something | orderBy:’key’…

Использование orderByметода случайной сортировки в этом вопросе отлично работает в AngularJS 1.1. var myApp = angular.module(‘myApp’,[]); function MyCtrl($scope) < $scope.list…

I’M iterating over an array of objects using ngRepeat . Объекты имеют поле «teamId». Внутри итерации я показываю поле с…

У меня есть эта коллекция / массив объектов $scope.users = [ , , , ]; $scope.currentUser =…

Я использую Firebase для хранения данных, и я знаю, что Firebase хранит данные как объекты, а не массивы. Я исправил…

Я использую ng-repeat на массиве данных, где каждое значение имеет » тип «либо » диаграммы», либо «таблицы». На повторе значения…

У меня есть контроллер, как это : var moduleFichiersDupliques = angular.module(‘fichiersDupliques’, []); moduleFichiersDupliques.controller(«FichiersDupliquesController», [ ‘$http’, ‘$log’, function($http, $log) < var…

Я пытаюсь использовать angular orderByдля упорядочивания нескольких полей, но получаю синтаксическую ошибку как: Синтаксическая ошибка, нераспознанное выражение: div[ng-repeat= ‘ r…

Я использую плагин jQuery для работы с Angular. Мне нужно вызвать функцию updateJustify () после того, как ng-repeat переупорядочил себя….

Я делаю небольшое приложение, которое сортирует список очков, которые пользователи имеют похож на лидеров игры. Я настроил ng-repeat над массивом…

Я новичок в AngularJS. Я пытаюсь отфильтровать список recipeобъектов, предоставляемых областью a recipeService. Мои объекты отображаются, но фильтр не применяется….

Я пытаюсь создать список терминов и их определений, но помещаю заголовок в начале каждого буквенного раздела. ТО ЕСТЬ Есть Apple…

Я не знаю, почему orderBy не работает с trackBy, это делает меня сумасшедшим �� Вот мой HTML код:

Мне нужно отсортировать массив объектов, но проблема в том, если какое-то свойство объектов null Образец [ < «foo»: 2, «bar»:…

Мне интересно, как правильно сортировать табличные данные, когда данные распределены по нескольким таблицам. У меня есть некоторые данные приложения, которые…

Два выпадающих списка ниже не генерируют массив лет. Мне также нужно, чтобы годы были отсортированы от самого раннего до последнего,…

Есть некоторые проблемы после заказа товаров в ng-repeat. После нажатия на пункт Открыть страницу с неправильным индексом. Мой пример HTML…

Мой массив:BS. Своя структура : Array[317] 0: Object $$hashKey: «022» name: «Los Angeles Comm.» . . . .. BS-это массив….


Я только начал изучать Angular и подумал бы, что это тривиально, но я не могу понять этого.. У меня есть…

Я не уверен, как подойти к этому вопросу. Я получаю JSON от сервера ….

Я применяю фильтр «orderby», но он не работает. Я получаю данные от API, который я дважды проверяю, приходит наверняка. Но…

AngularJS: Как написать фильтр по возрастанию сортировки

1 gene [2015-06-10 22:38:00]

Я изучаю AngularJS и как упражнение, пытающееся написать фильтр восходящего сортировки:

Это мой html файл:

Я что-то не так в цикле относительно сравнения значений.

Что я делаю не так?

2 ответа

3 Решение Jeremy [2015-06-10 22:47:00]

Ваш фильтр ничего не возвращал (отсутствующий оператор возврата)

Ng-init следует использовать только для псевдонимов, не рекомендуется декларировать в нем переменные. В вашем примере вы должны использовать ng-init, чтобы применить фильтр к вашему массиву, но сам массив должен быть объявлен в контроллере.

Ваш алгоритм сортировки не работает. Чтобы отсортировать простой массив, вы можете просто использовать метод sort() javascript.

Вот рабочий плункер с исправленными тремя точками:

Edit: Я думаю, вы хотели понять это как форму упражнения, поэтому мое решение касается только того, как вы пытались решить проблему. Как и другие упоминаемые, верно, что вы можете использовать фильтр orderby, чтобы сделать это проще в конце.

2 AGE [2015-06-10 22:47:00]

Как насчет orderBy:

имя префикса с знаком + означает восходящее, альтернативно — означает спуск.

Изменение: как следует из другого ответа, пожалуйста, воздержитесь от использования ng-init для объявления переменных/объектов. как вы можете видеть в документации AngularJS, простой контроллер можно использовать не только для большинства целей, но и более важно для упражнений.

AngularJs OrderBy фильтр правильно не сортировать данные

У меня есть массив клиента, отображаемый в HTML, используя нг-повтор от контроллера.

Здесь я пытаюсь отсортировать данные с помощью OrderBy фильтра. Но проблема в том, когда массив инициализируется он правильно отсортирован в порядке возрастания. Но когда я нажимаю на имя заголовок это chnages данные, но не опускается данные, как и ожидалось. Вот ход plunker:

Заменить $scope.reverse = !scope.reverse; с $scope.reverse = !$scope.reverse;

Вы пропустили $ до того scope .

Обновить:

Я добавляю этот ответ, чтобы сделать сортировку для всех индивидуальных значений с заголовком предикатом

Sort and Filter a Table Using Angular

When building Angular applications, one of the cornerstones we will use is `ng-repeat`. Showing data is something that we do in applications like when we show a table of users or whatever other data we need to show our users. Today we’ll be looking at a way to sort and filter our tabular data. This is a common feature that is always useful so let’s look at what we’ll be building and dive right into the code.

Our application will allow us to: — Show a table of data (`ng-repeat`) — Sort by ascending or descending columns (`orderBy`) — Filter by using a search field (`filter`) These are three common functions in any application and Angular let’s us implement these features in a very simple way. Let’s set up our sample application’s HTML and Angular parts and then look at how we can sort and filter.

We’ll be using Bootstrap and Font Awesome to style our app. Let’s take a look at the Angular module first. This will be a simple module with one controller where we define a few variables and the list of data we’ll show to our users (we’ll be using sushi, yum). The files we will need are:

Our demo is built inside of CodePen, so you can create the two files above or just work within your own CodePen. Here is the code for `app.js`

We have set the 3 variables and the list of sushi. Now let’s use this module in our HTML. Here is the HTML we’ll need for `index.html`:

Angular Sort and Filter

We are loading Bootstrap, Font Awesome, and Angular. We will also apply the Angular module named `sortApp` and the Angular controller called `mainController` to the tag.

We are also using an ngRepeat to loop over the sushi in our `$scope.sushi` array we created in our Angular module. Our app will now look like the following: Great. We have the list of data displayed all nicely for our users. Now let’s offer them some functionality by letting them sort the table.

## Sorting the Table

We will be accomplishing this sorting feature using two of the variables that we created earlier ( `$scope.sortType` and `$scope.sortReverse`). We will also be using the Angular orderBy filter. Basically, applying a combination of sortType and sortReverse variables to an orderBy clause in our `ng-repeat` will sort the table.

That’s all we need to change the sort order of our ng-repeat. If you refresh your page, you’ll see that your list is sorted by `name` in normal order. Now go into your Angular module and change the sortType variable to `$scope.sortType = ‘fish’` and refresh the page. You’ll now see the table sorted by Fish Type. The next step is to change the headings of our table so that they will change the `sortType` variable. That will automatically sort our table without refreshing the page (as is the Angular way).

### Making Table Headings Clickable

We’ll be adding links to our table headings. Let’s look at the `thead` section of our site and use `ng-click` to adjust the `sortType` variable.

Now as you click the links across your table headers, you’ll see your table sorted since we are setting the `sortType` variable using `ng-click`.

### Changing the Sort Order

Next up, we’ll be adding a way to change the sort order so users can sort by ascending or descending. The orderBy filter arguments offer a third parameter for `reverse`. We just have to pass in true or false to change the sort order. Currently we have it set to `false` since we defined that as one of the variables earlier (`$scope.sortReverse`). The way we will give users the option to reverse the sort is to add `sortReverse = !sortReverse` in the `ng-click` of our table headers. This will change the order if users click the link.

Just add that to all the other `ng-click`s in the code as well. Now if you click your header links, you’ll see the sort order changing. This isn’t very intuitive right now though since we don’t provide any sort of visual feedback that the sort is changing. Let’s add carets to show up and down to represent our current sort order. We’ll add an up and down caret here and then use ngShow and ngHide to show and hide the caret based on order

Now the up arrow will only show if `sortType` is name and `sortReverse` is set to true. Applying this to the other headers will give you the same effect. With a few Angular directives, we are now able to show proper feedback for sorting and for sort order. The last part of this tutorial will deal with filtering the table of data.

## Filtering the Table

Filtering data in an `ng-repeat` is fairly easy since Angular also comes with the filter module. There are only two things we need to do here: create the form and apply the form variable to the ng-repeat. Let’s create the form first. Above the code for the `table` and below the code for the `alert`.

A lot of that is Bootstrap markup to style our form beautifully, but the main line we need to worry about is the `input`. This is where we define our `ng-model` to adjust the searchFish variable. Now as we type into that input box, you should see that variable change in the alert box above. With that variable bound and ready to go, all we have to do is apply it to our `ng-repeat`.

Just like that, our filter will now be applied to the table. Go ahead and type into your filter box and see the table data change. You’ll also notice that the orderBy and filter will work together to find you the exact sushi roll that you want. http://codepen.io/sevilayha/pen/AmFLE

Using some built in Angular tools like ngRepeat, orderBy, filter, ngClick, and ngShow, we’ve been able to build a clean and fast table of data. This is a great look at the power that Angular has in building some great functionality into your own applications without too much work.

For more Angular goodness, here’s some other great articles: The Many Ways to Use ngClass Using ngShow and ngHide and Animating Them Single Page Animated Apps using ngView AngularJS Form Validation

Upgrade AngularJS Sorting Filters to Angular

In the early days of AngularJS, one of the most celebrated features was the ability to filter and sort data on the page using only template variables and filters. The magic of two-way data binding won over many converts to AngularJS and helped it spread like wildfire.


Today, though, the front end world prefers one-way data binding, and those orderBy and filter filters have ridden off into the 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+.)

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!

Our Starting Point

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.

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

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).

(And, if you’re confused on how to set up an ngUpgrade project with working builds, head over to Upgrading AngularJS. I’ve got detailed, step-by-step videos in the course to help you.)

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.

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.

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.

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

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:

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

(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).

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).

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-show s and replace with *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:

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.

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

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!

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!)

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.

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. *(Also, side note: in the sample code we mark this variable as private to demonstrate that it won’t work with Angular’s AOT compiler, which we cover later in the course. You can ignore that here and keep it public.) *

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

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):

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.

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:

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:

Now we can call the sort function on this.orders , but pass in our dynamic sort function with our 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.

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

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:

We’re tying our functions together like this because we’re only doing a simple toggle in our sort function for the sake of simplicity. 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.

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:

Again, this is a simple implementation of sorting, but I want to be sure 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.

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

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:

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

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

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.

Before we do that, let’s change the default sorting in our ngOnInit function to just be 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 a simple ) .


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 .

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:

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.

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:

  • We could make a class in our main app SCSS file.
  • We could write in-line CSS, although that’s almost never preferable.
  • We could take advantage of Angular’s scoped CSS using the styles option in the component decorator

We’re going to go with the last option, because it’s really simple and 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:

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!

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.

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.

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.

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

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

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:

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.

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.

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 simple 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:

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:

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.

Luckily, Angular provides a really easy way 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 it’s easy to catch which model is associated with which input if I just glance down the page.

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:

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

Does it all work?

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: Awesome, we’ve replaced another AngularJS feature!

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

Bonus: 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 paramters 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:.

In Angular 4, do this:

<> <>