Ответы пользователя по тегу Angular
  • Как кинуть событие в родительский компонент?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    this.sendCert.emit(); - то что тут между скобочками, а в данный момент тут ничего
    попадает вот сюда
    (sendCert)="sendCertTest(certAlias, certPassword)"
    certAlias, certPassword - будут undefined
    Плюс у события всего один параметр.

    И вообще непонятно зачем одни и те же данные туда сюда гонять.
    Ответ написан
  • Ошибка CORS при использование aiohttp и Angular8 как правильно настроить?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    не надо ничего дополнительно настраивать на бэке и ставить nginx, вебпаковского изкоробочного прокси для дев-режима достаточно
    https://angular.io/guide/build#proxying-to-a-backe...
    Значит что-то не так сделали.
    и не забывайте что запросы вы должны слать на 4200, никаких OPTIONS из браузера быть не должно.
    И запускать лучше явно указав прокси-конфиг, типа ng serve --proxy-config proxy.conf.json
    Ответ написан
    Комментировать
  • Причина ошибок в продакшн сборке в Angular?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    С помощью какого сервера вы открываете проект?
    <base href="/"> в index.html присуствует?
    Ответ написан
  • Как работают Promise в Angular?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    this.http.get возвращает Observable, это объект библиотеки rxjs, он не является промисом или thenable и к нему не может быть применен await
    Вы можете привести его к промису вот так
    return this.http.get(this.env.API_URL + 'video', options).toPromise()


    Однако в ангуляре нормальной практикой считается избегание промисов.
    И ваши методы дожны выглядеть так
    getToken(): Observable<string> {
        return from(this.storage.getItem('token'));
    }
    
    latest() {
      return this.getToken().pipe(
        switchMap(token => {
            const headers = new HttpHeaders({ auth: token });
            return this.http.get(this.env.API_URL + 'video', { headers });
        }),
      )
    }
    Ответ написан
    Комментировать
  • Как запустить Angular8 + NodeJS + MongoDB приложениe на сервере?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    Купить простейший vds или освоить какую-нибудь платформу для деплоя типа now.sh
    Монга предоставляет облачную базу бесплатно, если не более 500мб.
    А лучше NodeJS + MongoDB - вот эту часть выкинуть и сделать на firebase. Только с прослойкой на фронте, чтобы можно было легко переехать на полноценный бэк в случае нужды.
    Ответ написан
    1 комментарий
  • Динамические классы в CSS и HTML используя Angular 9?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    При стандартных настройках ангуляр добавляет хтмл-элементам компонента свою метку, типа _nghost-lli-c18 или _ngcontent-rja-c18
    Всем стилям компонента автоматически добавляется эта приписка, например в браузере будет выглядеть как
    a[_ngcontent-rja-c18] {
        color: red;
    }

    В Ангуляре это зовется "инкапсуляция стилей", является дефолтным поведением и может быть выключено или изменено на использование ShadowDOM.
    Таким образом стили компонента накладываются только на тэги в компоненте. Что-то там отдельно синхронизировать не нужно.
    Ответ написан
    1 комментарий
  • Вопрос по form control в ангуляре?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер

    Мне нужно, чтобы при самом первом запросе это поле не участвовало в запросе я этого добился тем, что убрал значение по дефолту в этом поле.

    поясните более развернуто, почему такое поведение?

    Пока выглядит так, что вам нужно проверять это в запросе, форма тут роли вообще не должна играть.
    И дефолтное значение у формы всегда есть, если не указали то это undefined.
    Ответ написан
  • Почему вылетает error 'Cannot read property 'subscribe' of undefined'?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    getCerts(): Observable<any> {
      // ...
      return new Observable(observer => {
        chrome.runtime.sendMessage(editorExtensionId, message, res=> {
          // ...
           observer.next(result);
           observer.complete();
        })
    }
    })


    Домашняя работа - сократить код используя https://rxjs.dev/api/index/function/bindCallback
    Ответ написан
    Комментировать
  • Как сгенерировать разные поля input?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    вот примерно так ток добавьте материал и чтение/сохранение в ls
    Ответ написан
    Комментировать
  • Как получить доступ к chrome в Angular?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    не надо слушать вредные советы :)
    Установите типы для хрома https://www.npmjs.com/package/@types/chrome

    а потом где-нибудь создаем токен для инжектора.
    export const CHROME = new InjectionToken('CHROME');

    в провайдерах апп-модуля по этому токену провайдим значение
    providers: [
      ...
      {
        provide: CHROME,
        useValue: window.chrome,
      }
      ...
    ]

    В конструкторе вашего компонента или сервиса
    constructor(
      @Inject(CHROME) private chrome: chrome,
    )


    Это делается для того чтобы иметь возможность когда нужно эту зависимость подменить. Например подсовывать моки для тестирования.
    Но вообще можно и просто chrome или window.chrome вызвать, если вы не паритесь по поводу подмен и вообще слежением за зависимостями. Главное объяснить тайпскрипту что это валидное имя. Ну т.е. доустановить типы.

    Я могу ошибиться в мелочах, т.к. не проверял, но правильный способ в общих чертах описал.
    Ответ написан
    2 комментария
  • Как прокручивать меню?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    Определить ширину контейнера в ngAfterViewInit
    При свайпе выставлять transform: translateX(ширина * индекс) с помощью Renderer2
    Анимацию на transform в стили.
    Ответ написан
    Комментировать
  • Почему не происходит запись в базу indexedDB?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    На вид все вроде ок, надо дебажить, перерести куда-нибудь в песочницу.
    Пока могу предложить свою обертку к indexedDB, вроде работает, не тестировал толком. Может наведет на размышление.
    DbService

    export interface DbConfig {
      /** prefix for indexed db name */
      name: string;
      /** keyPath in indexed db */
      keyPath?: string;
      /** keyPath of indexed db */
      objectName: string;
    }
    
    @Injectable()
    export class DbService<T = any> {
      private version = 1;
      private db$: Observable<IDBDatabase> = this.createDb(this.config.name, this.version);
    
      constructor(
        @Inject(DB_CONFIG) private config: DbConfig,
      ) { }
    
      private createDb(name: string, version?: number): Observable<IDBDatabase> {
        const openRequest: IDBOpenDBRequest = indexedDB.open(name, version);
    
        openRequest.onupgradeneeded = (evt: IDBVersionChangeEvent) => this.onUpgradeNeeded(openRequest);
    
        return this.fromIDBRequest(openRequest).pipe(
          shareReplay(1),
        );
      }
    
      private onUpgradeNeeded(openRequest: IDBOpenDBRequest): void {
        const db = openRequest.result;
        if (db.objectStoreNames.contains(this.config.objectName)) {
          return;
        }
        db.createObjectStore(this.config.objectName, { keyPath: this.config.keyPath });
      }
    
      public save(value: T, key?: IDBValidKey): Observable<IDBValidKey> {
        return this.db$.pipe(
          mergeMap((db: IDBDatabase) => this.fromIDBRequest(
            this.createIDBObjectStore(db, 'readwrite').put(value, key)
          )),
        );
      }
    
      public saveAll(values: T[]): Observable<IDBValidKey[]> {
        return from(values).pipe(
          mergeMap((value: T, index: number) => this.save(value, index)),
          toArray(),
        );
      }
    
      public delete(key: string): Observable<undefined> {
        return this.db$.pipe(
          mergeMap(db => this.fromIDBRequest(
            this.createIDBObjectStore(db, 'readwrite').delete(key),
          ))
        );
      }
    
      public clear() {
        return this.db$.pipe(
          mergeMap(db => this.fromIDBRequest(
            this.createIDBObjectStore(db, 'readwrite').clear(),
          ))
        );
      }
    
      public retreive(key: string): Observable<T> {
        return this.db$.pipe(
          mergeMap(db => this.fromIDBRequest(
            this.createIDBObjectStore(db, 'readonly').get(key)
          )),
        );
      }
    
      public retreiveAll(): Observable<T[]> {
        return this.db$.pipe(
          mergeMap(db => this.fromIDBRequest(
            this.createIDBObjectStore(db, 'readonly').getAll()
          )),
        );
      }
    
      private createIDBObjectStore(db: IDBDatabase, mode: IDBTransactionMode): IDBObjectStore {
        const transaction: IDBTransaction = db.transaction(this.config.objectName, mode);
        return transaction.objectStore(this.config.objectName);
      }
    
      private fromIDBRequest<R>(idbRequest: IDBRequest<R>): Observable<R> {
        return new Observable<R>(observer => {
          idbRequest.onsuccess = (evt: Event) => {
            observer.next(idbRequest.result);
            observer.complete();
            evt.stopPropagation();
          };
          idbRequest.onerror = (evt: Event) => {
            observer.error(idbRequest.error);
            evt.stopPropagation();
          };
        });
      }
    
      public selectDb() {
        return this.db$;
      }
    }

    Ответ написан
  • Как с помощью RxJs показать лоадер для медленного запроса?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    https://stackblitz.com/edit/angular-ws6pee
    задержки увеличены до 1000 и 2500 для наглядности
    В случае множественных загрузок возможны коллизии, надо будет дорабатывать.
    Лоадер, дебаунсер и таймауты можно и нужно изолировать в отдельном компоненте (или директиве), который будет получать текущее значение лоадера (тут оно setLoader) как инпут параметр.
    В принципе вообще можно сделать даже пайп.


    - если запрос длится более 500 мс, то показываем лоадер
    - если лоадер уже показан, то отображать его не менее 300 мс

    Если бы эти два числа были одинаковы, можно было обойтись одним debounceTime на лоадере.
    Ответ написан
  • Что ссылкой как ее вставить что бы правильно отображалась?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    <a [routerLink]="['/dashboard/micebot/']" [queryParams]="{ a: 'serv11111121'}">/micebot</a>
    Ответ написан
    1 комментарий
  • Angular2: как при авторизации обновить header.component?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    @Injectable()
    export class UserService {
        isAuthenticated$ = new ReplaySubject(1);
      
        constructor(private http: HttpClient) { }
         
        getUser() {
            return this.http.get('/server/api/userService').pipe(
              tap(data => this.isAuthenticated$.next(!!data['login'])),
            );
        }
    }


    export class HeaderComponent implements OnInit {
          user$: Observable<User>;
          isAuthenticated$: Observable<boolean>;
    
         constructor(private userService: UserService) { }        
    
          ngOnInit() {
            this.user$ = this.userService.getUser();
            this.isAuthenticated$ = this.userService.isAuthenticated$;
         }
    }


    При использовании AsyncPipe достаточно этого, хотя даже isAuthenticated - лишний.
    Ответ написан
    9 комментариев
  • Как использовать нескольких css-фреймворков в одном проекте, не прибегая к помощи SASS/SCSS?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    Сделать как написано в статье, скомпилить стили с помощью препроцессора, получившийся CSS подключить к проекту.
    Ответ написан
    Комментировать
  • Как в angular правильно вызвать асинхронный метод с параметром из html разметки?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    <span>{{ getAddressByCode(addressCode) | async }}</span>

    AsyncPipe умеет раскрывать промисы.
    Разумеется метод будет вызываться каждый раз при проверке изменений.


    существует ли возможность в ангуляре вызывать нормальные async методы, а не только RxJs?

    Angular это все еще js и работать с асинками в нем можно. Но как правило не нужно потому, что создаются совершенно лишние обертки, rx просто удобнее.
    Для реквестов используется xhr, и его событийная природа легко конвертируется в rx поток.
    Ответ написан
  • Как работает import в angular и какая оптимизация от sharedModule?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    Импорт модуля1 в модуль2 инициализирует инжектор модуля1 и он становится доступен для инжектора модуля2.
    Создаются экземпляры провайдеров модуля1, и декларируемые сущности модуля 1 и новые экземляры провайдеров модуля1 становятся видимыми для модуля2.
    Компоненты импортировать нельзя.

    Расположение по бандлам определяет вебпак, если нет лейзи модулей то все будет в main. Если будут лейзи, то общие импорты скорее всего тоже попадут в main.
    Ваш вариант 2 ближе к реальности.
    SharedModule не нужен. Он служит типа аггрегатором для разделяемых модулей, чтобы меньше было строчек в импортах.
    Ответ написан
    1 комментарий
  • Подписаться на роут?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    Нужно либо сменить роут, например добавив хэш или query param
    Либо выключить переиспользование компонента, тогда на каждый клик компонент будет инициализироваться заново. Поместив вот это куда-нибудь выше, например в app.component
    constructor(
        private router: Router,
      ) {
        this.router.routeReuseStrategy.shouldReuseRoute = function () {
          return false;
        };
        this.router.events.subscribe((evt) => {
          if (evt instanceof NavigationEnd) {
            this.router.navigated = false;
          }
        });
      }


    Есть так же вариант ловить все клики по routerLink и вызов navigate

    upd.
    а вообще вы же должны понимать, что вам не роут надо отслеживать, а выполнить ваши действия
    1. при инициализации компонента.
    2. при нажатии на кнопку.
    Выносится в метод и вызывается в нужном месте.
    Ответ написан
  • Как реализовать правильно данный Guard?

    Xuxicheta
    @Xuxicheta Куратор тега Angular
    инженер
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
      return this.auth.getUser().pipe( map(user => user.err == 0));
    }
    Ответ написан