Ответы пользователя по тегу Angular
  • Как создавать компоненты динамически в зависимости от данных с API, используя Angular?

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

    [
      { name: 'Chart 1', routerLink: ['/chart-1']},
      { name: 'Chart 2 ', routerLink: ['/chart-2']},
    ]


    Дальше на основе этого массива строится компонент с табами. А сами компоненты табов будут подгружаться при помощи роутера при переходе на таб.
    Ответ написан
    Комментировать
  • В чем преимущество Angular перед Vue или React?

    search
    @search
    мама говорит что я особенный
    Пользовался Ангуляром почти 3 года. Главный плюс Ангуляра в том что это платформа. В ней стандартизированно почти всё: от процесса бутстрепа до процесса деплоя. Включая работу с CLI, тестированием и еще много чем. Это огромный селлинг поинт для проектов корпоративного уровня: когда над проектом трудится много человек из разных стран. Им не нужно договариваться об архитектуре, тестировании, и т.п. потому что Ангуляр предоставляет готовые решения на многие проблемы.

    Лично я бы не стал пихать Ангуляр в проект уровня дэшборда или лендинга. Но для проекта уровня, например, клиент банка, Ангуляр может быть отличным кандитадом.

    Я не пользовался Вью никогда, поэтому не знаю что он предоставляет. Но после где-то двух лет на Реакте (огромный проект с микрофронтендной архитектурой для Dazn) впечатления такие: в целом весело. Очень хорошо подходит для прототипов и небольших проектиков. Но для энтерпрайз проекта я бы не стал его советовать, так как слишком много нерешенных или по-детски решённых проблем. Командам будет сложно договариваться между собой.

    Такие дела.
    Ответ написан
    Комментировать
  • Как устранить ошибку при запуске karma тестов для Angular в gitlab CI?

    search
    @search
    мама говорит что я особенный
    Поправьте karma.config.js:
    browsers: ['ChromeHeadlessNoSandbox'],
    customLaunchers: {
      ChromeHeadlessNoSandbox: {
        base: 'ChromeHeadless',
        flags: ['--no-sandbox']
      }
    },


    Вот обсуждение этой движни https://github.com/karma-runner/karma-chrome-launc...
    Ответ написан
    Комментировать
  • Как перенести подписку на стрим из метода, вызываемого юзером, в ngOnInit()?

    search
    @search
    мама говорит что я особенный
    Старайтесь свести работу с обзёрваблами к подписке на них через asyncPipe. В таком случае ангуляр будет менеджить подписки/отписки за вас.

    Как это корректно делать не подскажу, потому что сам пришел к этому слишком поздно к концу двухлетнего проекта и уже полтара года как не сталкивался с ангуляром. Но на вид это возможно. Имхо нужно сохранять голову на плечах и не пытаться вывернуться с RxJS во что бы то ни стало потому что через месяц самому будет непонятно как это работает.

    Хорошее правило работы с RxJS - стараться откладывать вызов subscribe на потом. Код будет гибче если ваши методы не вызвают subsctibe, а возвращают observable. А подписка на сам observable происходит где-то в другом месте (например в том же asyncPipe). Ну или в том месте, где уже просто никак без подписки :-) Многие начинающие ангулярщики боятся RxJS как огня и подписываются на обзёрвблы при первой возможности, а дальше менеджат код в привычном инперативном виде. Такой стиль кодирования обычно заканчивается жалобами на сам фреймворк (мол он ничего не умеет).
    Ответ написан
    Комментировать
  • Можно ли задать плавное появление директиве ngSwitch?

    search
    @search
    мама говорит что я особенный
    Да, это можно сделать при помощи ангуляровской системы анимации.

    Вот пример того как анимация реализована для ngFor https://stackblitz.com/edit/ng-animations?file=ani...
    Принцип не отличается от ngSwitch.

    Здесь можно почитать подробнее https://angular.io/guide/transition-and-triggers
    Ответ написан
    Комментировать
  • Как подключить SASS миксины для angular проекта?

    search
    @search
    мама говорит что я особенный
    Проблема в том что SASS файлы компонентов - это отдельные модули, не связанные с "глобальными" стилями. Для того чтоб переиспользовать миксины, переменные и прочее, создайте отдельный файл, например _utils.scss, где бы лежали эти самые миксины и переменные. И импортируйте _utils.scss в те компоненты, где они нужны.

    Несколько лет назад я попытался заморочиться и сделать так чтоб миксины подключались по умолчанию где-то из настроек, но с наскока у меня не получилось - это раз. А два - поразмыслив, я пришел к тому, что это не верно, потому что при глобализации миксинов программист теряет возможность чистого и прозрачного экспортирования компонент в сторонние модули. Такие дела.
    Ответ написан
    1 комментарий
  • Оцените код Angular?

    search
    @search
    мама говорит что я особенный
    Когда меня просят оценить код на Ангуляре, то всегда вангую непонимание Rx. Это одновременно самая сильная и самая слабая сторона Ангуляра. Сильная в том плане что это невероятно мощный инструмент. А слабая в том что порог вхождения в Rx крайне высок. Невозможно просто так взять, начать проект с RxJS, разобраться походу и в итоге сделать хорошо. Нужно заранее знать с чем имеешь дело. Я не знаю как объяснить эти принципы в двух словах, или дать какую-то формулу успеха.

    Вот лекция, которая в своё время мне помогла:

    https://www.youtube.com/watch?v=3LKMwkuK0ZE

    Она по RxJS 5, но принципиально ничего не поменялось.

    Это из того что сразу бросается в глаза почти на любом проекте, не только на вашем.

    Из плюсов:

    - понимание что такое компоненты
    - плоская структура проекта

    Из минусов (не считая Rx):
    - отсутствие модулей

    Я бы еще поставил под сомнение необходимость папок services и shared, но это скорее всего вкусовщина. Кстати, если у кого-то сейчас бомбануло от предыдущего предложения, можете плиз направить меня куда-то где бы это по-человечески объяснялось? А то я реально не понимаю зачем нужны эти папки, и зачем провайдеры, работающие с Http называть сервисами. Я так подозреваю что народ копирует эту идею друг у друга. Но могу быть с удовольствием неправ.
    Ответ написан
    1 комментарий
  • Как связать компоненты между страницами?

    search
    @search
    мама говорит что я особенный
    Вынесите объявление сервиса в `providers` главного модуля. И уберите объявление сервиса из `providers` других модулей.

    Каждый раз когда вы добавляете сервис в `providers` модуля, анугяр создаёт экземпляр сервиса именно для этого модуля. И в другом модуле этот экземпляр виден не будет.
    Ответ написан
    Комментировать
  • Angular - Не работают стандартные значения переменой?

    search
    @search
    мама говорит что я особенный
    Только ручками, тайпскрипт за вас это чинить не будет.

    // Класс здесь не нужен. Старайтесь предпочитать интерфейсы классам если у объекта нет методов
    export interface NameSurName {
      name: string;
      surname: string;
    }
    
    ...
    
    this.nameSurName = {
      name: '',
      surename: 'Иванов',
      ...resp.data
    }


    На вопрос "почему так" ответ: тайпскрит не добавляет в код никакой магии. Конечный код скомпилированный из тайпскрипта выглядет в JS почти так же как и с тайпскриптом, только без типов. Короче, TS не занимается преобразованием типов за вас.

    Вот есть официальный playground от создателей. Можно ради интереса иногда попроверять что получится из вашего TS кода.
    Ответ написан
    Комментировать
  • Merge несколько observable - как узнать какой именно observable сработал?

    search
    @search
    мама говорит что я особенный
    В таком случае было бы разумно сделать сделать нужные действия для каждого из обзёрваблов по отдельности.

    merge(
      observable1.pipe(
        // do stuff related to form 1
      ),
      observable2.pipe(
        // do stuff related to form 2
      ),
      ...
    )
    Ответ написан
    Комментировать
  • Проблема с Access-Control-Expose-Headers?

    search
    @search
    мама говорит что я особенный
    `Access-Control-Allow-Origin` - это хедер ответа от сервера, а не хедер запроса. Он должен быть выставлен на сервере. Если вы не знаете с какого домена будет приходить запрос, то нужно выставлять `Access-Control-Allow-Origin: *`

    Эту проблему невозможно решить на клиенте, но ангуляр предоставляет сделать прокси на время разработки (тут хотел вставить ссылку на документацию, но тупой тостер запрещает использовать ссылки) . Этот прокси не будет работать на проде/стейджинге. Так что проблему всё равно прийдётся решать путём установки нужных хедеров на серваке.

    Если что, фраза "No 'Access-Control-Allow-Origin' header is present on the requested resource." на русский язык переводится как "Хедер 'Access-Control-Allow-Origin' не представлен на запрашиваемом ресурсе"
    Ответ написан
    Комментировать
  • Ошибка http запроса при подключении SSL почему?

    search
    @search
    мама говорит что я особенный
    Это называется CORS https://developer.mozilla.org/ru/docs/Web/HTTP/CORS

    Это можно поправить только на стороне сервера, передав вот такой хедер: Access-Control-Allow-Origin: domain.ru

    Этим хедером вы разрешите сайтам на domain.ru совершать запросы к вашему серверу. Если сервер не передает такой хедер, то запросы режет сам браузер и на стороне клиента это не исправить никак.

    Если вам заранее не известно на каком домене будет находиться клиент, то можно передавать Access-Control-Allow-Origin: *
    Ответ написан
    Комментировать
  • Почему не работает long polling?

    search
    @search
    мама говорит что я особенный
    Это происходит потому что PHP лочит сессию на каждом запросе. Это ставит в очередь другие ajax запросы. Для того чтоб освободить залоченную сессию можно выполнить

    $request->session()->save();

    где-нибудь перед while.

    $request->session()->save() в недрах фреймворка вызывает session_write_close() что освобождает сессию и даёт дорогу другим запросам.

    Вся эта колбасня с локами сессионных файлов нужна для того чтоб несколько запросов подряд не запоганили сессию. Если захотите что-нибудь записать в сессию после вызова $request->session()->save(), то, возможно прийдётся заново открывать сессию. Я хз, сделает ли ларавел это за вас или нет. На вашем месте советую убедиться самостоятельно, чтоб потом с бубном не плясать.
    Ответ написан
    Комментировать
  • Могу ли я настроить angular 7 приложение на запуск не в корневой папке?

    search
    @search
    мама говорит что я особенный
    ng build --prod --base-href /app/ должен помочь
    Ответ написан
    Комментировать
  • Как вернуть данные или сделать еще два запроса в Rx.js в зависимости от результата первого запроса?

    search
    @search
    мама говорит что я особенный
    Это делается через switchMap:

    this.httpClient.get('/check-email').pipe(
      switchMap(emailResult => {
        if (emailResult !== exists) {
          return of(dataForNonExistingEmail);
        }
        
        return forkJoin(
          this.httpClient.get('/user-data1'),
          this.httpClient.get('/user-data2')
        );
      })
    )
    Ответ написан
    3 комментария
  • Как правильно передавать данные через сервис Angular?

    search
    @search
    мама говорит что я особенный
    Для вашего случая существует лучшая практика: так называемые умные и глупые компоненты: https://medium.com/@dan_abramov/smart-and-dumb-com... (это оригинальная статья от автора реакта, но в ангуляре принципы такие же)

    В нашем случае компоненты search и result - глупые компоненты, которые только и делают, что возвращают строку ввода (search) и отображают данные (result). Так же у нас имеется умный компонент searchResults, который знает как отреагировать на данные из search и правильно отобразить result.

    Search и Result ничего не должны знать об HttpService. Он в них не инжектится.

    SearchComponent:

    import { Component, EventEmitter, Output } from '@angular/core';
    
    @Component({
        selector: 'search',
        templateUrl: './result.component.html',
        styleUrls: ['./result.component.scss']
    })
    export class SearchComponent {
    
        public query: string;
    
        @Output() onQuery: EventEmitter<string> = new EventEmitter();
    
        constructor() {}
    
        public handlerEnterSearch() {
            this.onQuery.emit(this.query)
        }
    }


    search.html:

    <div class="input-group input-group-lg p-5">
        <input
            [(ngModel)]="query"
            type="text"
            class="form-control"
            placeholder="Что ищем?"
            (keyup.enter)="handlerEnterSearch()"
        >
        <div class="input-group-append">
            <button class="btn btn-primary" type="button" (click)="handlerEnterSearch()">Найти фильм</button>
        </div>
    </div>


    result.component.ts

    import { Component, OnInit, Input } from '@angular/core';
    import { HttpService } from '../http.service'
    
    @Component({
      selector: 'result',
      templateUrl: './result.component.html',
      styleUrls: ['./result.component.scss']
    })
    export class ResultComponent implements OnInit {
    
      // Вот эти items выводятся в html результата
      @Input()
      items: any[];
    
      constructor(){}
    }


    search-result.html:

    <search (onQuery)="doSearch($event)">
    <result [items]="result">


    search-result.component.ts:

    import { Component, OnInit } from '@angular/core';
    import { HttpService } from '../http.service'
    
    @Component({
        selector: 'search-result',
        templateUrl: './search-result.component.html',
        styleUrls: ['./search-result.component.scss']
    })
    export class SearchResultComponent implements OnInit {
    
        items:any[];
    
        constructor(private httpService: HttpService){
    
        }
    
        // Вот это неудачная часть. Её можно сделать веселее, но для этого необходимо понимать как устроен RxJS.
        // Я не знаю как это объяснить без написания отдельной статьи.
        // На первое время такой подход сойдёт.
        doSearch(query: string) {
            this.httpService.getFilms(query).subscribe((items) => {
              this.items = items;
            })
        }
    }


    Использование сервисов для передачи данных между компонентами в ангуляре - это самые распространённые грабли во фреймворке. Причём эти грабли настолько хитрые, что большинство программистов даже не понимает что ходит по ним. Самый верный способ не наступать на грабли - это забыть навсегда про private и public переменные в сервисах (другими словами сервис не должен иметь состояние). Без этого можно жить и причём легко и спокойно если начать использовать NxRx для хранения состояния системы.
    Ответ написан
    2 комментария
  • Как в RxJS сделать переодичный вызов в n времени, только после завершения текущей итерации?

    search
    @search
    мама говорит что я особенный
    Как-то так:

    this.httpClient.request(...).pipe(
      repeatWhen(complete => complete.pipe(delay(20000))
    ).subscribe(result => console.log(result))
    Ответ написан
    Комментировать
  • Оценить приложение?

    search
    @search
    мама говорит что я особенный
    Вот классный проект, который задаёт планку программирования на ангуляре https://angular-checklist.io/default/checklist/arc...

    Можете пробежаться по всем пунктам и сравнить с тем что есть сейчас.

    Как верно заметил Дмитрий Лузанов, сразу бросается в глаза непонимание принципов работы RxJS. Вот видео, которое помогло мне разобраться в этом деле: https://www.youtube.com/watch?v=3LKMwkuK0ZE . Там старая версия RxJS, но принципы не поменялись.

    От себя добавлю, что хранить состояние системы в переменных сервисов (это я про items у ItemService) - это грабли. Не наступать на эти грабли поможет понимание RxJS (сорри, уже надоел, наверное, но в ангуляре без него никуда). И/или подключение NgRx.
    Ответ написан
    Комментировать
  • Typescript/Angular: что не так с возвратом результата асинхронной функции?

    search
    @search
    мама говорит что я особенный
    Вроде, если сделать
    axios.get<Room[]>('somepath/kek:1488?SeigHeil&joking=true')...

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

    UPD: еще такой момент, ожидается что сервак возвращает массив Rooms, так что rooms.push(response.data); не заработает как ожидалось потому что в итоге получится что переменная rooms будет содержать всего один элемент, и этот элемент будет массивом. Чтоб было понятнее о чём я говорю, попробуйте в консоли браузера выполнять следующее: let arr1 = [], arr2 = [1,2,3]; arr1.push(arr2); console.log(arr1);

    Но вобще весь getAll() можно сделать проще:

    public getAll(): Promise<Room[]> {
        return axios.get<Room[]>('somepath/kek:1488?SeigHeil&joking=true')
          .then(response => response.data)
          .catch(err => console.log(err))
    }


    Так же проще?

    C axios никогда не работал, так что этот ответ может быть полной лажей. Но попробуйте предложенный вариант. Судя по описанию типов, всё должно получиться как ожидается.
    Ответ написан