{"id":299648,"date":"2020-03-04T15:00:12","date_gmt":"2020-03-04T15:00:12","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=299648"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=299648","title":{"rendered":"Angular: \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0444\u043e\u0440\u043c\u044b \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0432 \u043d\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u044b"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/491062\/\">\u0420\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0432 \u043d\u0430\u0448\u0438\u0445 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u043d\u0435\u0440\u0435\u0434\u043a\u043e \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u0438\u0437 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u043a\u0438\u0440\u043f\u0438\u0447\u0438\u043a\u043e\u0432-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043d\u044b\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0438 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043d\u0430\u043c \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432. \u0422\u0430\u043a, \u043a\u0430\u043a \u044d\u0442\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0432 Angular.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435:<\/h3>\n<p>  <\/p>\n<ul>\n<li> \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u00ab\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0444\u043e\u0440\u043c\u044b \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0421\u041d\u0418\u041b\u0421\u00bb;<\/li>\n<li> \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0432\u043e\u0434\u0438\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u043c\u0430\u0441\u043a\u0435;<\/li>\n<li> \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0432\u0432\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445;<\/li>\n<li> \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u044b;<\/li>\n<li> \u043d\u0435\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438;<\/li>\n<li> \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043e\u0434\u043d\u0430\u0436\u0434\u044b \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438;<\/li>\n<li> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Angular Material.<\/li>\n<\/ul>\n<p>  <\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h3>\n<p>  <\/p>\n<h4>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442<\/h4>\n<p>  <\/p>\n<pre><code class=\"plaintext\">ng new input-snils<\/code><\/pre>\n<p>  <\/p>\n<h4>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438<\/h4>\n<p>  \u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u0430\u043c Angular Material<\/p>\n<pre><code class=\"plaintext\">ng add @angular\/material<\/code><\/pre>\n<p>  \u041f\u043e\u0442\u043e\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043b\u043e\u0436\u0438\u0442\u044c \u043c\u0430\u0441\u043a\u0443 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0441\u0430\u043c\u0438 \u0421\u041d\u0418\u041b\u0421 \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9A%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%BE#%D0%A1%D1%82%D1%80%D0%B0%D1%85%D0%BE%D0%B2%D0%BE%D0%B9_%D0%BD%D0%BE%D0%BC%D0%B5%D1%80_%D0%B8%D0%BD%D0%B4%D0%B8%D0%B2%D0%B8%D0%B4%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BB%D0%B8%D1%86%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D1%81%D1%87%D1%91%D1%82%D0%B0_(%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F)\">\u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b<\/a>.<\/p>\n<p>  \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438:<\/p>\n<pre><code class=\"plaintext\">npm install ngx-mask ru-validation-codes<\/code><\/pre>\n<p>  <\/p>\n<h3>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u044b<\/h3>\n<p>  <\/p>\n<h4>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 localStorage<\/h4>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0432 localStorage.<\/p>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0432\u0437\u044f\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 LS, \u043d\u043e \u0432 \u0410\u043d\u0433\u0443\u043b\u044f\u0440\u0435 \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0441\u0442\u0430\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434, \u0430 \u0432\u0441\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u043c. \u042d\u0442\u043e \u0442\u0430\u043a \u0436\u0435 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<p>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u0441\u0435 \u0441\u0432\u043e\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0437 DI \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430. \u0412\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u044f \u043a\u043e\u0442\u0430 \u041c\u0430\u0442\u0440\u043e\u0441\u043a\u0438\u043d\u0430 \u2014 \u0447\u0442\u043e\u0431\u044b \u043a\u0443\u043f\u0438\u0442\u044c \u0443 \u0438\u043d\u0436\u0435\u043a\u0442\u043e\u0440\u0430 \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u043e\u0435, \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0434\u0430\u0442\u044c \u0438\u043d\u0436\u0435\u043a\u0442\u043e\u0440\u0443 \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u043e\u0435. <\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440<\/p>\n<p>  <b>window.provider.ts<\/b><\/p>\n<pre><code class=\"javascript\">import { InjectionToken } from '@angular\/core';  export function getWindow() {   return window; }  export const WINDOW = new InjectionToken('Window', {   providedIn: 'root',   factory: getWindow, });<\/code><\/pre>\n<p>  \u0427\u0442\u043e \u0442\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442? \u0418\u043d\u0436\u0435\u043a\u0442\u043e\u0440 DI \u0432 Angular \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b \u0438 \u043e\u0442\u0434\u0430\u0435\u0442 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441 \u043d\u0438\u043c\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u044b. \u0422\u043e\u043a\u0435\u043d \u2014 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 InjectionToken, \u0441\u0442\u0440\u043e\u043a\u0430 \u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441. \u0422\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 InjectionToken root-\u0443\u0440\u043e\u0432\u043d\u044f \u0438 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u0444\u0430\u0431\u0440\u0438\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0439 <code>window<\/code>.<\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c window, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 LocalStorage<br \/>  <b>storage.service.ts<\/b><\/p>\n<pre><code class=\"javascript\">@Injectable({   providedIn: 'root' }) export class StorageService {   readonly prefix = 'snils-input__';    constructor(     @Inject(WINDOW) private window: Window,   ) {}    public set&lt;T&gt;(key: string, data: T): void {     this.window.localStorage.setItem(this.prefix + key, JSON.stringify(data));   }    public get&lt;T&gt;(key: string): T {     try {       return JSON.parse(this.window.localStorage.getItem(this.prefix + key));     } catch (e) { }   }    public remove(key: string): void {     this.window.localStorage.removeItem(this.prefix + key);   } }<\/code><\/pre>\n<p>  StorageService \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442 window \u0438\u0437 \u0438\u043d\u0436\u0435\u043a\u0442\u043e\u0440\u0430 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u042f \u043d\u0435 \u0441\u0442\u0430\u043b \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u043c, \u0434\u0430\u0431\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0438 \u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439.<\/p>\n<h4>FormPersistModule<\/h4>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u044b.<\/p>\n<p>  <b>form-persist.service.ts<\/b><\/p>\n<pre><code class=\"javascript\">@Injectable({   providedIn: 'root' }) export class FormPersistService {   private subscriptions: Record&lt;string, Subscription&gt; = {};    constructor(     private storageService: StorageService,   ) { }    \/**    * @returns restored data if exists    *\/   public registerForm&lt;T&gt;(formName: string, form: AbstractControl): T {     this.subscriptions[formName]?.unsubscribe();     this.subscriptions[formName] = this.createFormSubscription(formName, form);      return this.restoreData(formName, form);   }    public unregisterForm(formName: string): void {     this.storageService.remove(formName);      this.subscriptions[formName]?.unsubscribe();     delete this.subscriptions[formName];   }    public restoreData&lt;T&gt;(formName: string, form: AbstractControl): T {     const data = this.storageService.get(formName) as T;     if (data) {       form.patchValue(data, { emitEvent: false });     }      return data;   }    private createFormSubscription(formName: string, form: AbstractControl): Subscription {     return form.valueChanges.pipe(       debounceTime(500),     )       .subscribe(value =&gt; {         this.storageService.set(formName, value);       });   } } <\/code><\/pre>\n<p>  FormPersistService \u0443\u043c\u0435\u0435\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443 \u0441\u0435\u0431\u044f \u0444\u043e\u0440\u043c\u044b \u043f\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0432 LS. <br \/>  \u041f\u0440\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0442\u0430\u043a \u0436\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u043d\u043e\u0435 \u0438\u0437 LS \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0447\u0442\u043e \u0444\u043e\u0440\u043c\u0430 \u0443\u0436\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b\u0430\u0441\u044c \u0440\u0430\u043d\u0435\u0435. <\/p>\n<p>  \u041e\u0442\u043c\u0435\u043d\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 (<code>unregisterForm<\/code>) \u043f\u0440\u0435\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u0432 LS.<\/p>\n<p>  \u0425\u043e\u0447\u0435\u0442\u0441\u044f \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e, \u0430 \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u044d\u0442\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0432 \u043a\u043e\u0434\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. Angular \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0442\u0432\u043e\u0440\u0438\u0442\u044c \u0447\u0443\u0434\u0435\u0441\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432, \u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439.<\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0443<br \/>  <b>form-persist.directive.ts<\/b><\/p>\n<pre><code class=\"javascript\">@Directive({   selector: 'form[formPersist]', \/\/ tslint:disable-line: directive-selector }) export class FormPersistDirective implements OnInit {   @Input() formPersist: string;    constructor(     private formPersistService: FormPersistService,     @Self() private formGroup: FormGroupDirective,   ) { }    @HostListener('submit')   onSubmit() {     this.formPersistService.unregisterForm(this.formPersist);   }    ngOnInit() {     const savedValue = this.formPersistService.registerForm(this.formPersist, this.formGroup.control);     if (savedValue) {       this.formGroup.control.markAllAsTouched();     }   } } <\/code><\/pre>\n<p>  FormPersistDirective \u043f\u0440\u0438 \u043d\u0430\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430 \u0444\u043e\u0440\u043c\u0443 \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u0442 \u0438\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u043d\u0436\u0435\u043a\u0442\u043e\u0440\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0443 \u2014 FormGroupDirective \u0438\u0437 \u0438 \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0442\u0442\u0443\u0434\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u044b \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432 FormPersistService.<\/p>\n<p>  \u0421\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0439 \u043a\u043b\u044e\u0447 \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u0430, \u0441\u0430\u043c\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0441\u0432\u043e\u0435\u0433\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430.<\/p>\n<p>  \u041f\u0440\u0438 \u0441\u0430\u0431\u043c\u0438\u0442\u0435 \u0444\u043e\u0440\u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0442\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 submit \u0441 \u043f\u043e\u043c\u043e\u0449\u044c HostListener.<\/p>\n<p>  \u0422\u0430\u043a \u0436\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0443 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0433\u0434\u0435 \u043e\u043d\u0430 \u0441\u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430. \u0425\u043e\u0440\u043e\u0448\u0435\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  <b>form-persist.module.ts<\/b><\/p>\n<pre><code class=\"javascript\">@NgModule({   declarations: [FormPersistDirective],   exports: [FormPersistDirective] }) export class FormPersistModule { }<\/code><\/pre>\n<p>  <\/p>\n<h3>\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0444\u043e\u0440\u043c\u044b \u00ab\u0421\u041d\u0418\u041b\u0421\u00bb<\/h3>\n<p>  \u041a\u0430\u043a\u0438\u0435 \u043d\u0430 \u043d\u0435\u0433\u043e \u0432\u043e\u0437\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0438?<\/p>\n<p>  \u0412 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<h4>snilsValidator<\/h4>\n<p>  Angular \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0442\u044c \u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430\u043c \u0444\u043e\u0440\u043c \u0441\u0432\u043e\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u044b, \u0438 \u043f\u043e\u0440\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0441\u0432\u043e\u0439. \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0421\u041d\u0418\u041b\u0421 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0432\u043d\u0435\u0448\u043d\u044e\u044e ru-validation-codes \u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c.<\/p>\n<p>  <b>snils.validator.ts<\/b><\/p>\n<pre><code class=\"javascript\">import { checkSnils } from 'ru-validation-codes';  export function snilsValidator(control: AbstractControl): ValidationErrors | null {   if (control.value === ''  || control.value === null) {     return null;   }    return checkSnils(control.value)     ? null     : { snils: 'error' }; }<\/code><\/pre>\n<p>  <\/p>\n<h4>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u0442 InputSnilsComponent<\/h4>\n<p>  \u0428\u0430\u0431\u043b\u043e\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0438\u043d\u043f\u0443\u0442\u0430, \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Angular Material.<\/p>\n<p>  \u0421 \u043e\u0434\u043d\u0438\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c, \u043d\u0430 \u0438\u043d\u043f\u0443\u0442 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043b\u043e\u0436\u0435\u043d\u0430 \u043c\u0430\u0441\u043a\u0430 \u0432\u0432\u043e\u0434\u0430, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 ngx-mask, \u043e\u0442 \u043d\u0435\u0435 \u0442\u0443\u0442 \u0438\u043d\u043f\u0443\u0442-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b mask \u2014 \u0437\u0430\u0434\u0430\u0435\u0442 \u043c\u0430\u0441\u043a\u0443 \u0438 dropSpecialCharacters \u2014 \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0438\u0437 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u0446\u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043c\u0430\u0441\u043a\u0438. <\/p>\n<p>  \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0439 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <a href=\"https:\/\/jsdaddy.github.io\/ngx-mask-page\/main\">jsdaddy.github.io\/ngx-mask-page\/main<\/a><\/p>\n<p>  \u0412\u043e\u0442 \u0448\u0430\u0431\u043b\u043e\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<br \/>  <b>input-snils.component.html<\/b><\/p>\n<pre><code class=\"xml\">&lt;mat-form-field appearance=&quot;outline&quot;&gt;   &lt;input     matInput     autocomplete=&quot;snils&quot;     [formControl]=&quot;formControl&quot;     [mask]=&quot;mask&quot;     [dropSpecialCharacters]=&quot;false&quot;     [placeholder]=&quot;placeholder&quot;     [readonly]=&quot;readonly&quot;     [required]=&quot;required&quot;     [tabIndex]=&quot;tabIndex&quot;   &gt;   &lt;mat-error [hidden]=&quot;formControl | snilsErrors: 'required'&quot;&gt;\u0421\u041d\u0418\u041b\u0421 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c&lt;\/mat-error&gt;   &lt;mat-error [hidden]=&quot;formControl | snilsErrors: 'format'&quot;&gt;\u0421\u041d\u0418\u041b\u0421 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0443&lt;\/mat-error&gt;   &lt;mat-error [hidden]=&quot;formControl | snilsErrors: 'snils'&quot;&gt;\u0421\u041d\u0418\u041b\u0421 \u043e\u0448\u0438\u0431\u043e\u0447\u0435\u043d&lt;\/mat-error&gt; &lt;\/mat-form-field&gt;<\/code><\/pre>\n<p>  \u0412\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441, \u0430 \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u0430 formControl | snilsErrors? \u042d\u0442\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u0430\u0439\u043f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043e\u043a, \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c.<\/p>\n<p>  <b>snils-errors.pipe.ts<\/b><\/p>\n<pre><code class=\"javascript\">type ErrorType = 'required' | 'format' | 'snils';  @Pipe({   name: 'snilsErrors',   pure: false, }) export class SnilsErrorsPipe implements PipeTransform {    transform(control: AbstractControl, errorrType: ErrorType): boolean {     switch (errorrType) {       case 'required': return !control.hasError('required');       case 'format': return !control.hasError('Mask error');       case 'snils': return control.hasError('Mask error') || !control.hasError('snils');       default: return false;     }   } }<\/code><\/pre>\n<p>  \u041f\u0430\u0439\u043f \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u043c, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. <\/p>\n<p>  \u041f\u0430\u0439\u043f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u0438\u043f\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 \u0438 \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 \u0442\u0440\u0435\u0445 \u0442\u0438\u043f\u043e\u0432: <\/p>\n<ul>\n<li> \u00abrequired\u00bb \u2014 \u044d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043e\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0439 \u0432 Angular \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b RequiredValidator<\/li>\n<li> \u00absnils\u00bb \u2014 \u044d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 snilsValidator<\/li>\n<li>\u00abMask error\u00bb \u2014 \u044d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043e\u0442 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b MaskDirective \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 ngx-mask<\/li>\n<\/ul>\n<p>  \u0418 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0431\u0443\u043b\u0435\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u2014 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u043b\u0438 \u043d\u0435\u0442.<\/p>\n<p>  \u0410 \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0441\u0430\u043c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<br \/>  <b>input-snils.component.ts<\/b><\/p>\n<pre><code class=\"javascript\">@Component({   selector: 'app-input-snils',   templateUrl: '.\/input-snils.component.html',   styleUrls: ['.\/input-snils.component.css'],   encapsulation: ViewEncapsulation.None,   providers: [     {       provide: NG_VALUE_ACCESSOR,       useExisting: forwardRef(() =&gt; InputSnilsComponent),       multi: true     },     {       provide: NG_VALIDATORS,       useExisting: forwardRef(() =&gt; InputSnilsComponent),       multi: true,     },     {       provide: STATE_VALUE_ACCESSOR,       useExisting: forwardRef(() =&gt; InputSnilsComponent),     },   ] }) export class InputSnilsComponent implements OnInit, ControlValueAccessor, StateValueAccessor, OnDestroy {   public mask = '000-000-000 00';   public formControl = new FormControl('', [snilsValidator]);   private sub = new Subscription();    @Input() readonly: boolean;   @Input() placeholder = '\u0421\u041d\u0418\u041b\u0421';   @Input() tabIndex = 0;   @Input() required: boolean;    private onChange = (value: any) =&gt; { };   private onTouched = () =&gt; { };   registerOnChange = (fn: (value: any) =&gt; {}) =&gt; this.onChange = fn;   registerOnTouched = (fn: () =&gt; {}) =&gt; this.onTouched = fn;     ngOnInit() {     this.sub = this.linkForm();   }    ngOnDestroy() {     this.sub.unsubscribe();   }    private linkForm(): Subscription {     return this.formControl.valueChanges.subscribe(value =&gt; {       this.onTouched();       this.onChange(value);     });   }    writeValue(outsideValue: string): void {     if (outsideValue) {       this.onTouched();     }     this.formControl.setValue(outsideValue, { emitEvent: false });   }    setDisabledState(disabled: boolean) {     disabled       ? this.formControl.disable()       : this.formControl.enable();   }    validate(): ValidationErrors | null {     return this.formControl.errors;   }    setPristineState(pristine: boolean) {     pristine       ? this.formControl.markAsPristine()       : this.formControl.markAsDirty();      this.formControl.updateValueAndValidity({ emitEvent: false });   }    setTouchedState(touched: boolean) {     touched       ? this.formControl.markAsTouched()       : this.formControl.markAsUntouched();      this.formControl.updateValueAndValidity({ emitEvent: false });   } }<\/code><\/pre>\n<p>  \u0422\u0443\u0442 \u043c\u043d\u043e\u0433\u043e \u0432\u0441\u0435\u0433\u043e \u0438 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 ControlValueAccessor, \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0435\u0441\u0442\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Angular, \u0438\u043b\u0438 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0443\u0442 <a href=\"https:\/\/tyapk.ru\/blog\/post\/angular-custom-form-field-control\">tyapk.ru\/blog\/post\/angular-custom-form-field-control<\/a><\/p>\n<p>  \u0427\u0442\u043e \u0442\u0443\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u044f?<\/p>\n<p>  \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u0444\u043e\u0440\u043c\u044b formControl, \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043a \u0435\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u0432\u0435\u0440\u0445, \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434\u044b onChange \u0438 onTouched.<br \/>  \u0418 \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u0444\u043e\u0440\u043c\u044b \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u043a \u043d\u0430\u043c \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434\u044b writeValue \u0438 setDisabledState \u0438 \u043e\u0442\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 formControl.<\/p>\n<p>  \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0442\u0443\u0442 \u0435\u0441\u0442\u044c \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d STATE_VALUE_ACCESSOR, \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 StateValueAccessor \u0438 \u043f\u0430\u0440\u0430 \u043b\u0438\u0448\u043d\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 setPristineState \u0438 setTouchedState. \u041e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u044a\u044f\u0441\u043d\u0435\u043d\u044b \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p>  \u0410 \u043f\u043e\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0435\u0433\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c<br \/>  <b>input-snils.module.ts<\/b><\/p>\n<pre><code class=\"javascript\">@NgModule({   declarations: [InputSnilsComponent, SnilsErrorsPipe],   imports: [     CommonModule,     MatFormFieldModule,     MatInputModule,     NgxMaskModule.forChild(),     ReactiveFormsModule,   ],   exports: [InputSnilsComponent], }) export class InputSnilsModule { }<\/code><\/pre>\n<p>  <\/p>\n<h3>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u0432 \u0432 \u044d\u043b\u0435\u043c\u0435\u043d\u0442<\/h3>\n<p>  \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 ControlValueAccessor \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043d\u044e\u0430\u043d\u0441: <\/p>\n<p>  \u0420\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f touched \u0438 pristine (\u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u00ab\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u00bb). <\/p>\n<ul>\n<li>pristine \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e true \u0438 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 false \u043a\u043e\u0433\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u0430<\/li>\n<li> touched \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e false \u0438 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 true \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u043f\u043e\u0442\u0435\u0440\u044f\u043b \u0444\u043e\u043a\u0443\u0441<\/li>\n<\/ul>\n<p>  \u0422\u0430\u043a \u0436\u0435 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u043e \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043e\u0442\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 ControlValueAccessor, \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u044d\u0442\u043e formControl.<\/p>\n<p>  \u0410 \u043e\u0448\u0438\u0431\u043a\u0438 mat-error \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0433\u0434\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b touched. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 FormPersistDirective \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 markAllAsTouched, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0444\u043e\u0440\u043c\u044b \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043e \u0438\u0437 localStorage. \u041d\u043e \u043e\u0448\u0438\u0431\u043a\u0430 mat-error \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 ControlValueAccessor \u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 touched \u043f\u043e \u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 false.<\/p>\n<p>  \u041d\u0443\u0436\u0435\u043d \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 ControlValueAccessor, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e StateValueAccessor.<\/p>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<p>  <b>state-value-accessor.token.ts<\/b><\/p>\n<pre><code class=\"javascript\">export const STATE_VALUE_ACCESSOR = new InjectionToken&lt;StateValueAccessor&gt;('STATE_VALUE_ACCESSOR');<\/code><\/pre>\n<p>  <b>state-value-accessor.interface.ts<\/b>  <\/p>\n<pre><code class=\"javascript\">export interface StateValueAccessor {   setTouchedState?(touched: boolean): void;   setPristineState?(pristine: boolean): void; }<\/code><\/pre>\n<p>  \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043a\u043b\u0430\u0441\u0441, \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0435\u0433\u043e \u0438\u043c\u0435\u043b (\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e) \u0434\u0432\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u0430. \u042d\u0442\u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0432 InputSnilsComponent \u0438 \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442 \u044d\u0442\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435 formControl.<\/p>\n<p>  \u0417\u0430\u0442\u0435\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430, \u0447\u0442\u043e\u0431\u044b \u0441\u0432\u044f\u0437\u0430\u0442\u044c NgControl \u0438 \u043d\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 StateValueAccessor. \u041d\u0435\u043b\u044c\u0437\u044f \u0442\u043e\u0447\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u0443 \u0444\u043e\u0440\u043c\u044b \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043d\u043e \u043c\u044b \u0437\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0444\u043e\u0440\u043c\u044b Angular \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u044e\u0449\u0438\u0439 \u0446\u0438\u043a\u043b\u0430 \u0434\u0435\u0442\u0435\u043a\u0446\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. \u0423 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438 \u0435\u0433\u043e \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f lifecycle \u0445\u0443\u043a ngDoCheck, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430.<\/p>\n<h4>FormStatusesDirective<\/h4>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0443<br \/>  <b>form-statuses.directive.ts<\/b><\/p>\n<pre><code class=\"javascript\">const noop: (v?: boolean) =&gt; void = () =&gt; { };  @Directive({   selector: '[formControlName],[ngModel],[formControl]' \/\/ tslint:disable-line: directive-selector }) export class FormStatusesDirective implements DoCheck, OnInit {   private setSVATouched = noop;   private setSVAPristine = noop;    constructor(     @Self() private control: NgControl,     @Self() @Optional()  @Inject(STATE_VALUE_ACCESSOR) private stateValueAccessor: StateValueAccessor,   ) { }    ngOnInit() {     if (this.stateValueAccessor?.setTouchedState) {       this.setSVATouched = wrapIfChanges(touched =&gt; this.stateValueAccessor.setTouchedState(touched));     }      if (this.stateValueAccessor?.setPristineState) {       this.setSVAPristine = wrapIfChanges(pristine =&gt; this.stateValueAccessor.setPristineState(pristine));     }   }    ngDoCheck() {     this.setSVAPristine(this.control.pristine);     this.setSVATouched(this.control.touched);   } }<\/code><\/pre>\n<p>  FormStatusesDirective \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044b \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 StateValueAccessor. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443 \u0438\u043d\u0436\u0435\u043a\u0442\u043e\u0440\u0430 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043e \u0442\u043e\u043a\u0435\u043d\u0443 STATE_VALUE_ACCESSOR, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 StateValueAccessor \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u0437\u0430\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0438\u0442\u044c.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043f\u043e \u0442\u043e\u043a\u0435\u043d\u0443 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e, \u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043c\u0435\u0442\u043e\u0434\u044b setSVATouched \u0438 setSVAPristine \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0436\u0435 StateValueAccessor \u043d\u0430\u0439\u0434\u0435\u043d, \u0442\u043e \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u044b setTouchedState \u0438 setPristineState \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0437\u0432\u0430\u043d\u044b \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439.<\/p>\n<p>  \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043d\u0430\u0431\u0434\u0438\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0443 \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430<br \/>  <b>form-statuses.module.ts<\/b><\/p>\n<pre><code class=\"javascript\">@NgModule({   declarations: [FormStatusesDirective],   exports: [FormStatusesDirective] }) export class FormStatusesModule { }<\/code><\/pre>\n<p>  <\/p>\n<h3>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430<\/h3>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0430\u043c\u0443 \u0444\u043e\u0440\u043c\u0443. \u041f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0435\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 AppComponent.<br \/>  \u0428\u0430\u0431\u043b\u043e\u043d<br \/>  <b>app.component.html<\/b><\/p>\n<pre><code class=\"xml\">&lt;section class=&quot;form-wrapper&quot;&gt;   &lt;form     class=&quot;form&quot;     [formGroup]=&quot;form&quot;     formPersist=&quot;inputSnils&quot;   &gt;     &lt;app-input-snils       class=&quot;input-snils&quot;       formControlName=&quot;snils&quot;       [required]=&quot;true&quot;     &gt;&lt;\/app-input-snils&gt;      &lt;button       class=&quot;ready-button&quot;       mat-raised-button       [disabled]=&quot;form.invalid&quot;       type=&quot;submit&quot;     &gt;       Submit     &lt;\/button&gt;   &lt;\/form&gt; &lt;\/section&gt;<\/code><\/pre>\n<p>  \u041d\u0430 \u0444\u043e\u0440\u043c\u0435 \u0432\u0438\u0441\u0438\u0442 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430 FormPersistDirective, Angular \u0443\u0437\u043d\u0430\u0435\u0442 \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u0430 form[formPersist].<\/p>\n<p>  \u0428\u0430\u0431\u043b\u043e\u043d\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u043e\u0434\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0443 \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e<br \/>  <b>app.component.ts<\/b><\/p>\n<pre><code class=\"javascript\">@Component({   selector: 'app-root',   templateUrl: '.\/app.component.html',   styleUrls: ['.\/app.component.css'] }) export class AppComponent {   public form = new FormGroup({     snils: new FormControl('', [Validators.required])   }); }<\/code><\/pre>\n<p>  \u041a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0441 \u0444\u043e\u0440\u043c\u043e\u0439 \u0432\u044b\u0448\u0435\u043b \u043a\u0440\u0430\u0439\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0438 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043b\u0438\u0448\u043d\u0435\u0433\u043e.<\/p>\n<p>  \u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/qb\/qa\/ko\/qbqakozek8aqxafpbojkbn3b65y.png\"\/><\/p>\n<p>  \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u043d\u0430 <a href=\"https:\/\/github.com\/xuxicheta\/input-snils\/tree\/master\/src\">GitHub<\/a><br \/>  \u0414\u0435\u043c\u043e \u043d\u0430 <a href=\"https:\/\/stackblitz.com\/edit\/github-dc5mfb\">stackblitz<\/a><br \/>  \u041a\u043e\u0434 \u043d\u0430 stackblitz \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f, \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0432\u0435\u0440\u0441\u0438\u044f typescript \u0442\u0430\u043c \u0435\u0449\u0435 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u044d\u043b\u0432\u0438\u0441-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440.<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/491062\/\"> https:\/\/habr.com\/ru\/post\/491062\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/491062\/\">\u0420\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u0432 \u043d\u0430\u0448\u0438\u0445 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u043d\u0435\u0440\u0435\u0434\u043a\u043e \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u0438\u0437 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u043a\u0438\u0440\u043f\u0438\u0447\u0438\u043a\u043e\u0432-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043d\u044b\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0438 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043d\u0430\u043c \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432. \u0422\u0430\u043a, \u043a\u0430\u043a \u044d\u0442\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0432 Angular.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-299648","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/299648","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=299648"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/299648\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=299648"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=299648"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=299648"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}