Redux в Angular. Создание UI компонентов для отображения новостей.
В данной статье реализуются виджеты для ввода списка новостей, а также страницы с полным отображением новости.
Для главной страницы необходимы три виджета:
- виджет промо новостей;
- виджет популярных новостей;
- виджет последних новостей.
Виджет промо новостей реализуется в виде карусели новостей, который размещается в директории 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