Redux в Angular. Создание UI компонентов для отображения новостей.

Aleksandr Serenko
F.A.F.N.U.R
Published in
3 min readNov 24, 2022

В данной статье реализуются виджеты для ввода списка новостей, а также страницы с полным отображением новости.

Для главной страницы необходимы три виджета:

  • виджет промо новостей;
  • виджет популярных новостей;
  • виджет последних новостей.

Виджет промо новостей реализуется в виде карусели новостей, который размещается в директории libs/redux/posts/ui/promo.

В компоненте с промо новостями PostsPromoComponent идет подписка на список промо новостей и отображение их в виде карусели.

Компонент карусели был рассмотрен в одной из предыдущих статей.

Так как приложение может использоваться самостоятельно и как удаленное, то приходится реализовывать костыль с навигацией внутри remote приложения:

const path = this.pathRemote ? ['/', this.pathRemote, 'post', slide.uuid] : ['/post', slide.uuid];

Виджет популярных новостей реализуется в виде списка новостей, где будет небольшое превью и заголовок новости. Виджет размещается в директории libs/redux/posts/ui/popular.

В компоненте виджета популярных новостей PostsPopularComponent идет подписка на список популярных новостей. Для отображения конкретной новости используется компонент PostPopularComponent.

Виджет последних новостей реализуется в виде списка новостей, где будет превью и заголовок новости. Виджет размещается в директории libs/redux/posts/ui/last.

Компонент списка последних новостей PostsLastComponent аналогичен компоненту с популярными новостями, за исключением верстки.

Создание страницы новостей

Создадим новую страницу для вывода виджетов новостей.

В разметке компонента страницы с новостями выводятся три виджета, где виджет промо новостей занимает всю доступную ширину страницы, а виджеты с последними и популярными новостями выводятся в виде колонок.

Заголовок был вынесен в отдельный модуль:

В шапке страницы вывода новостей показывается какая из текущих реализаций Redux используется в конкретный момент.

Задание версии redux осуществляется в приложении с установкой токена:

@NgModule({
providers: [
{
provide: REDUX_TYPE,
useValue: 'NGRX',
},
...
],
})
export class AppCoreModule {}

Виджет создания новой новости

На странице с новостями есть еще один виджет — PostCreateComponent. Данный компонент позволяет создавать новые новости.

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

Диалоговое окно с формой имеют следующий вид:

В шаблоне выводиться форма с использованием angular material.

В компоненте создается типизированная форма:

readonly form = new FormGroup<FormFor<PostCreate>>({
uuid: new FormControl(uuidv4(), { nonNullable: true, validators: [Validators.required] }),
title: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.minLength(2)] }),
body: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.minLength(20)] }),
image: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.minLength(5)] }),
promo: new FormControl(false, { nonNullable: true, validators: [Validators.required] }),
});

Подробнее о типизированных формах можно найти в документации, а также в статье — Типизированные формы в Angular.

В onInit добаляется подписка на успех/провал создания новой новости:

ngOnInit(): void {
this.postFacade.createSuccess$
.pipe(
tap(() => {
this.submitted = false;
this.matDialogRef.close();
this.changeDetectorRef.markForCheck();
}),
takeUntil(this.destroy$)
)
.subscribe();

this.postFacade.createFailure$
.pipe(
tap(() => {
this.submitted = false;
this.form.enable();
this.changeDetectorRef.markForCheck();
}),
takeUntil(this.destroy$)
)
.subscribe();
}

А метод отправки формы проверяет валидность формы и если данные валидны, то создается новая новость:

onSubmit(): void {
this.form.markAllAsTouched();
if (this.form.valid && !this.submitted) {
this.submitted = true;
this.form.disable();
this.postFacade.create(this.form.getRawValue());
} else {
// TODO: Scroll to error field
}
this.changeDetectorRef.markForCheck();
}

Создание страницы с полным отображением новости

Аналогично странице с виджетами, создается страница с просмотром полной новости.

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

<angular-samples-container automation-id="container">
<angular-samples-post-header automation-id="header"></angular-samples-post-header>
<angular-samples-row web="">
<angular-samples-column web="8">
<angular-samples-post-article [post]="post" automation-id="article"></angular-samples-post-article>
</angular-samples-column>
<angular-samples-column web="4">
<angular-samples-posts-popular automation-id="popular"></angular-samples-posts-popular>
</angular-samples-column>
</angular-samples-row>
</angular-samples-container>

Вывод новости вынесен в отдельный компонент -PostArticleComponent.

Компонент принимает новость на вход и в дальнейшем просто выводит поля.

<div><img automation-id="image" [src]="post.image" alt="" /></div>
<h2 automation-id="title">{{ post.title }}</h2>
<p automation-id="date">{{ post.created | date: 'shortDate' }}</p>
<div automation-id="body" [innerHTML]="post | postBody"></div>

Так как для простоты использовался обычный текст, необходим pipe который добавить переносы строк в html:

Выше приведенных компонентов достаточно, чтобы реализовать страницу со списком новостей.

Ссылки

Оглавление

Предыдущая статья — Создание фейкового API для новостей.

Следующая статья — Концепты и понятия в Redux.

Все исходники находятся на github, в репозитории:

Для того, чтобы посмотреть состояние проекта на момент написания статьи, нужно выбрать соответствующий тег — redux.

Подписывайтесь на блог, чтобы не пропустить новые статьи про Angular, и веб-разработку. Medium | Telegram| VK |Tw| Ln

--

--

Aleksandr Serenko
F.A.F.N.U.R

Senior Front-end Developer, Angular evangelist, Nx apologist, NodeJS warlock