Все сервисы Хабра

Сообщество IT-специалистов

Ответы на любые вопросы об IT

Профессиональное развитие в IT

Удаленная работа для IT-специалистов

Войти на сайт
  • Все вопросы
  • Все теги
  • Пользователи

Хабр Q&A — вопросы и ответы для IT-специалистов

Получайте ответы на вопросы по любой теме из области IT от специалистов в этой теме.

Узнать больше
другие проекты хабра
  • Хабр
  • Карьера
  • Фриланс
Задать вопрос
yurzui

Алексей Зуев

  • 474
    вклад
  • 0
    вопросов
  • 350
    ответов
  • 88%
    решений
Ответы
  • Информация
  • Ответы
  • Вопросы
  • Комментарии
  • Подписки
  • Нравится
  • Достижения
  • Как обойти все узлы внутри родителя (детей, внуков, правнуков, ...)?

    yurzui
    Алексей Зуев @yurzui
    Уберите return и избавьтесь от глобальной переменной i

    for (var i = 0;

    https://jsfiddle.net/zspe25p4/
    Ответ написан более трёх лет назад
    1 комментарий
    1 комментарий
  • Почему родитель не слышит дочерний элемент?

    yurzui
    Алексей Зуев @yurzui
    Сверьте название вашего Output с тем, что вы написали в шаблоне

    (recieveChanges)="recieveChanges($event)"
              ||
    @Output() changeEvent = new EventEmitter<string>();


    Две вертикальные линии обозначают то, что эти названия должны совпадать.

    Так что попробуйте

    (changeEvent)="recieveChanges($event)"

    вдруг заработает
    Ответ написан более трёх лет назад
    1 комментарий
    1 комментарий
  • В чём дело со слайдером, или почему не работает его функционал при подключении к Angular 2?

    yurzui
    Алексей Зуев @yurzui
    Салют!

    Попробуйте написать где-нибудь в стилях

    carousel {
      display: block;
    }


    или :host если стили внутри компонента
    Ответ написан более трёх лет назад
    2 комментария
    2 комментария
  • Как поймать наведение мышки?

    yurzui
    Алексей Зуев @yurzui
    Я подозреваю вы думали использовать mouseover событие вместо onmouseover
    jsfiddle
    Ответ написан более трёх лет назад
    Комментировать
    Комментировать
  • Как автоматически проскролить до таблицы?

    yurzui
    Алексей Зуев @yurzui
    Есть много вариантов, вот к примеру один из вариантов

    Определяем template reference variable

    <table *ngIf="view" #table>

    Следим за появлением таблицы на странице и скроллим к ней в случае появления

    @ViewChild('table') 
    set tableEl(el: ElementRefl) {
      if(el) {
        el.nativeElement.scrollIntoView();
      }
    }


    Живой пример
    Ответ написан более трёх лет назад
    40 комментариев
    40 комментариев
  • Как правильно работать с datatable от Angular Material?

    yurzui
    Алексей Зуев @yurzui
    Таблица не совсем простая получается, мы обязаны передавать dataSource как объект типа DataSource из @angular/cdk

    /**
       * Provides a stream containing the latest data array to render. Influenced by the table's
       * stream of view window (what rows are currently on screen).
       */
      @Input()
      get dataSource(): DataSource<T> { return this._dataSource; }


    Вот вам следующий шаг

    import { DataSource } from '@angular/cdk'
    import { Observable } from 'rxjs/Observable'
    import 'rxjs/add/observable/of'
    
    export class MyDataSource extends DataSource<any> {
      connect(): Observable<any[]> {
        return Observable.of([
          {id: 1, title: 'Test 1'},
          {id: 2, title: 'Test 2'},
          {id: 3, title: 'Test 3'},
        ]);
      }
    
      disconnect() {}
    }
    
    
    public dataSource: DataSource = new MyDataSource();


    https://plnkr.co/edit/I5gnn3XzosabC8lQCrEo?p=preview

    Это как бы подталкивает нас не забрасывать изучать rxjs и познавать всю его силу. Далее идите в примеры на сайте https://material.angular.io/components/table/examples, там более продвинутая версия connect метода, где используется merge оператор
    Ответ написан более трёх лет назад
    9 комментариев
    9 комментариев
  • HostListener document:click для одного компонента среди множества копий?

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

    @Directive({
        selector: '[outsideClickHandler]',
    })
    export class OutsideClickDirective {
        @Output('outsideClickHandler') close = new EventEmitter();
    
        isOpen: boolean = false;
    
        constructor(private elRef: ElementRef) {}
    
        @HostListener('document:click', ['$event'])
        public handleClick(event) {
          if (!this.isOpen)  {
              this.isOpen = true;
          } else if (!this.elRef.nativeElement.contains(event.target)) {
              this.close.emit();
          }
        }
    }


    после этого легко используйте ее в своем шаблоне

    <div class="editable-edit-box" (outsideClickHandler)="onClose()">


    Живой пример
    Ответ написан более трёх лет назад
    Комментировать
    Комментировать
  • Как создать переменную в шаблоне?

    yurzui
    Алексей Зуев @yurzui
    Angular 4

    Вот так может сработать, только нужно чтобы эта функция всегда true в булевом эквиваленте возвращала
    <z *ngIf="zOf(x, y) as z" (disabled)="disabled(z)" (selected)="selected(z)"></z>


    иначе такой вариант
    <z *ngIf="{ of: zOf(x, y) } as z" (disabled)="disabled(z.of)" (selected)="selected(z.of)"></z>


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

    И я очень уверен что в @Output код будет исполняться при срабатывании соответствующего подписчика. Так что я не понимаю зачем вам тут переменная
    Ответ написан более трёх лет назад
    1 комментарий
    1 комментарий
  • Вместо объекта json - undefined. Anguar 2 и 4, как вы обмениваетесь данными через RestAPI?

    yurzui
    Алексей Зуев @yurzui
    Вот этот код
    console.log("usersService body: "+body);

    дает вам массив в консоли. Потом вы зачем-то пишете

    return body.data || { };

    у массива нет свойства data, соответственно ваш сервис возвращает пустой объект.

    Эту строчку вообще удалите

    console.log("appComponent.users: "+this.users);
    никто не получает данные из асинхронного запроса таким образом

    this.usersService.getUsers()
        .subscribe(
            users => {
               console.log(users);
               this.users = users;
            },
            error =>  this.errorMessage = <any>error);

    Итого

    private extractData(res: Response) {
        return res.json() || [];
    }
    Ответ написан более трёх лет назад
    Комментировать
    Комментировать
  • Почему при запуске тестов на Angular2 результат не отображается в браузере?

    yurzui
    Алексей Зуев @yurzui
    Потому что карма по умолчанию не отображает результаты jasmine test runner.

    Обычно для этого используют репортер karma-jasmine-html-reporter , который как я вижу из вашего конфига вы пытались настроить.

    Я уверен, что вы установили этот пакет через

    npm install karma-jasmine-html-reporter --save-dev
    И у вас наверно что-то мелькает в браузере. И главная проблема скорее всего в том, что карма очищает output после исполнения скриптов. Чтобы этого избежать может помочь настройка

    client: {
      clearContext: false
    }

    https://gist.github.com/alexzuza/f26abad42e6a7658c...

    P.S. где-то в версии `1.0.0-beta.32.x` это добавили по умолчанию https://github.com/angular/angular-cli/pull/4567
    Ответ написан более трёх лет назад
    Комментировать
    Комментировать
  • Как работать с глобальной переменной и BehaviorSubject / Angular2?

    yurzui
    Алексей Зуев @yurzui
    У BehaviorSubject объекта есть метод getValue

    this.cartService.cart.next(this.cartService.cart.getValue().push(prod));


    Можете посмотреть пример здесь https://github.com/jhades/angular2-rxjs-observable...
    Ответ написан более трёх лет назад
    Комментировать
    Комментировать
  • Angular 2: Удаление элементов страницы в зависимости от роли?

    yurzui
    Алексей Зуев @yurzui
    Вы упустили то, что в вашем случае директива выступает как бы хостом для элементов, но вы ничего не добавляли в этот контейнер под названием viewContainerRef.

    Попробуйте написать структурную директиву как это:

    @Directive({
        selector: '[hasRole]'
    })
    export class HasRoleDirective implements OnInit {
        @Input() hasRole: Array<string>;
    
        constructor(private viewContainerRef: ViewContainerRef, 
                           private template: TemplateRef<any>) {}
    
        ngOnInit() {
            this.checkRoles('user');
        }
    
        checkRoles(userRole: string) {
            console.log("Роль пользователя: " + userRole);
            if (!this.hasRole || this.hasRole.indexOf(userRole) != -1) {
                console.log("Есть доступ");
                this.viewContainerRef.createEmbeddedView(this.template);
            } else {
                this.viewContainerRef.clear();
                console.log("Доступ запрещен");
            }
        }
    }


    Используйте просто со звездочкой

    <p *hasRole="['admin', 'user']"><Блок идят только Админ и Пользователь</p>
    <div *hasRole="['admin']">Тестовый блок который видит только Админ</div>


    Это аналогично этому

    <template [hasRole]="['admin', 'user']">
       <p>Тестовый параграф которые видят только Админ и Пользователь</p>
    </template>
    <template [hasRole]="['admin']">
       <div>Тестовый блок который видит только Админ</div>
    </template>

    Т.е. здесь template(будет текстовой нодой) выступает в роли хоста-контейнера для элементов. И мы в зависимости от наших условий решаем - добавлять или нет эти элементы в контейнер, которые пойдут следом за хостом. Если планируете динамически менять права, то можете использовать сеттер для инпута. Вот вам шаблон https://github.com/angular/angular/blob/2.4.5/modu...
    Ответ написан более трёх лет назад
    18 комментариев
    18 комментариев
  • Как поймать событие попытки обновления станицы?

    yurzui
    Алексей Зуев @yurzui
    Может быть вы ищите это window.onbeforeunload
    Ответ написан более трёх лет назад
    2 комментария
    2 комментария
  • Как получить json данные в Angular2 приложении?

    yurzui
    Алексей Зуев @yurzui
    Вариант 1 - получаем Observable и используем AsyncPipe, который сделает всю грязную работу за нас

    html
    *ngFor="let release of releases | async"

    component
    releases: Observable<any[]>;
    
    constructor(private releasesService: ReleasesService) {}
    
    ngOnInit() {
      this.releases = this.releasesService.getReleases();
    }


    Вариант 2 - сами подписываемся

    releases: any[];
    
    constructor(private releasesService: ReleasesService) {}
    
    ngOnInit() {
      this.releasesService.getReleases()
         .subscribe(data => this.releases = data);
    }
    Ответ написан более трёх лет назад
    2 комментария
    2 комментария
  • Как динамически применять дефолтныe pipe?

    yurzui
    Алексей Зуев @yurzui
    Вариант 1
    Использовать кастомный pipe Живой пример:
    import { UpperCasePipe, LowerCasePipe } from '@angular/common'
    
    const PIPES_COLLECTION = {
      'uppercase': new UpperCasePipe(), 
      'lowercase': new LowerCasePipe()
    };
    
    @Pipe({
      name: 'dynamicPipe'
    })
    export class DynamicPipe implements PipeTransform {
      transform(val, pipeName: string) {
        return PIPES_COLLECTION[pipeName].transform(val);
      }
    }


    Минус в том, что нужно вручную перечислять доступные наборы пайпов
    ___________________________________________________________________________________________________________________

    Вариант 2
    Использовать директиву, которая динамически генерирует результат через Compiler Живой пример

    Минусы - генерируется лишняя разметка, нужно больше времени на компиляцию и не будет работать с AOT
    @Directive({
      selector: '[dynamicPipe]'
    })
    export class DynamicPipeDirective {
      @Input() dynamicPipe: DynamicPipeModel;
      cmpRef: ComponentRef<any>;
    
      constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {}
    
      ngAfterViewInit() {
        const data = this.dynamicPipe.name;
        const pipe = this.dynamicPipe.pipe;
    
        @Component({
          selector: 'dynamic-comp',
          template: '{{ data | ' + pipe  + '}}'
        })
        class DynamicComponent  {};
    
        @NgModule({
          imports: [CommonModule],
          declarations: [DynamicComponent]
        })
        class DynamicModule {}
    
        this.compiler.compileModuleAndAllComponentsAsync(DynamicModule)
          .then((moduleWithComponentsFactory) => {
            const compFactory = moduleWithComponentsFactory.componentFactories.find(x => x.componentType === DynamicComponent);
            const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
            this.cmpRef = this.vcRef.createComponent(compFactory, 0, injector, []);
            this.cmpRef.instance.data = data;
          });
      }
    
      ngOnDestroy() {
        if(this.cmpRef) {
          this.cmpRef.destroy();
        }
      }
    }
    Ответ написан более трёх лет назад
    1 комментарий
    1 комментарий
  • Почему так доолго грузится приложение на Angular2?

    yurzui
    Алексей Зуев @yurzui
    Я советую вам делать бандлы для продакшна

    huge-number-of-files-generated-for-every-angularjs...
    angular-2-how-to-bundle-for-production

    Потом посмотрите в сторону AOT(Ahead-of-time compilation) Это поможет вам избавиться от compiler.umd.js и ускорит открытие страницы, так как не будет тратиться время на компиляцию в браузере.

    aot-compiler
    Getting your Angular 2 library ready for AoT
    Ahead-of-time compilation how to
    Try Angular 2 AoT compilation

    И можете еще заглянуть в репозиторий

    Universal Angular 2
    What is Angular Universal?
    Angular Universal For The Rest Of Us

    Это поможет вам ускорить ваше приложение. Только я не понимаю, зачем вам для такой визитки angular2 или я еще не знаю всех скрытых возможностей приложения?

    И обязательно загляните в рекомендации, которые вам скинул Максим Тимофеев. Приложение, построенное на angular2, ничем не отличается от обычного и его можно тюнинговать всеми возможными способами
    Ответ написан более трёх лет назад
    3 комментария
    3 комментария
  • Как правильно забрать значение из директивы Datepicker?

    yurzui
    Алексей Зуев @yurzui
    Обычно такие кастомные директивы делают совместимыми с инструментами для работы с формами - делают кастомными контролами формы через реализацию интерфейса ControlValueAccessor
    custom-form-controls-in-angular-2

    Еще могу увлекательную статью на тему форм посоветовать, где применяется подобная техника
    Building Tesla's battery range calculator with Ang...

    Вот пример того, как это можно реализовать для datepicker (Plunker)

    @Component({
      selector: 'saUiDatepicker',
      template: `<input type="text" #input class="form-control datepicker" placeholder="{{placeholder}}" [(ngModel)]="value" (blur)="onBlur()">`,
      providers: [CUSTOM_UI_DATEPICKER_CONTROL_VALUE_ACCESSOR]
    })
    export class UiDatepickerComponent implements OnInit, ControlValueAccessor {
      private innerValue: any = '';
    
      private onTouchedCallback: () => void = () => { };
      private onChangeCallback: (_: any) => void = () => { };
    
      get value(): any {
        return this.innerValue;
      };
    
      set value(newValue: any) {
        if (newValue === this.innerValue) return;
    
        this.innerValue = newValue;
        this.onChangeCallback(newValue);
      }
    
      @Input() options: any;
      @Input() placeholder: any;
    
      @ViewChild('input') el: ElementRef;
    
      onBlur() {
        this.onTouchedCallback();
      }
    
      writeValue(value: any) {
        if (value !== this.innerValue) {
          this.innerValue = value;
        }
      }
    
      registerOnChange(fn: any) {
        this.onChangeCallback = fn;
      }
    
      registerOnTouched(fn: any) {
        this.onTouchedCallback = fn;
      }
    
      ngOnInit() {
        let options = $.extend(this.options || {}, {
          onSelect: (selectedDate) => {
            this.onChangeCallback(selectedDate);
          }
        });
    
        System.import('jquery-ui').then(() => {
          const datePicker = $(this.el.nativeElement).datepicker(options);
          if (this.value) {
            datePicker.datepicker("setDate", this.value);
          }
        });
      }
    }


    Использование в template-driven forms
    <form #templateForm="ngForm" (ngSubmit)="submit(templateForm.value)">
      <saUiDatepicker name="data" [(ngModel)]="data" [options]="{...}" 
             placeholder="Выберите дату"></saUiDatepicker>    
      <button type="submit">Submit</button>
    </form>

    И reactive/model-driven forms

    <form [formGroup]="reactiveForm">
       <saUiDatepicker formControlName="data" [options]="{...}" 
           placeholder="Выберите дату"></saUiDatepicker>  
        <pre>{{ reactiveForm.value | json }}</pre> 
    </form>
    
    constructor(private fb: FormBuilder) {}
      
    ngOnInit() {
      this.reactiveForm = this.fb.group({
          data: ''
      });
    }
    Ответ написан более трёх лет назад
    2 комментария
    2 комментария
  • Как принудительно заставить Vue.js синхронизировать данные?

    yurzui
    Алексей Зуев @yurzui
    В вашем случае проще всего сделать так

    <input type="text" v-model="city" v-on:awesomplete-select="city = $event.text.value">


    Просто подписаться на событие, которое срабатывает на элементе при выборе из выпадающего списка
    Ответ написан более трёх лет назад
    Комментировать
    Комментировать
  • Как вывести символ любой валюты через currency?

    yurzui
    Алексей Зуев @yurzui
    В Angular2 currency pipe в конечном счете исполняет вот эту функцию

    new Intl.NumberFormat([locales[, options]])

    https://developer.mozilla.org/ru/docs/Web/JavaScri...

    Чтобы pipe вернул русский символ рубля. ему нужно подставить правильную локаль ru-RU. Ее можно переопределить глобально, но раз ты используешь разные котировки, то можно сделать кастомный pipe

    К примеру вот так может работать (Plunker):

    import { CurrencyPipe } from '@angular/common';
    
    const map = {
      'RUB': 'ru-RU',
      'JPY': 'ja-JP'
    }
    
    @Pipe({name: 'localizedCurrency'})
    export class LocalizedCurrencyPipe implements PipeTransform {
      transform(value: any, currencyCode: string = 'USD', 
              symbolDisplay: boolean = false, digits: string = null): string {
        return new CurrencyPipe(map[currencyCode]).transform(value, currencyCode, symbolDisplay, digits);
      }
    }
    Ответ написан более трёх лет назад
    1 комментарий
    1 комментарий
  • Как можно совместно использовать ngFor и ngif?

    yurzui
    Алексей Зуев @yurzui
    Можно
    1) обернуть в ng-container

    <ng-container *ngFor="let row of review.penalty">
      <tr *ngIf="row.sum > 10">
        <td>{{row.name}}</td>
        <td>{{row.sum | number:'.2'}}</td>  
      </tr>
    </ng-container>

    Пример

    2) использовать template
    <template ngFor let-row [ngForOf]="review.penalty">
      <tr *ngIf="row.sum > 10">
        <td>{{row.name}}</td>
        <td>{{row.sum | number:'.2'}}</td>  
      </tr>
    </template>

    Пример
    Ответ написан более трёх лет назад
    3 комментария
    3 комментария
Оценили как «Нравится»
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • Следующие →
Самые активные сегодня
  • gzhegow
    Григорий Васильков
    • 12 ответов
    • 0 вопросов
  • mayton2019
    • 9 ответов
    • 0 вопросов
  • sergey-gornostaev
    Сергей Горностаев
    • 6 ответов
    • 0 вопросов
  • Adamos
    Adamos
    • 6 ответов
    • 0 вопросов
  • Dr. Bacon
    • 6 ответов
    • 0 вопросов
  • vabka
    Василий Банников
    • 6 ответов
    • 0 вопросов
  • © Habr
  • О сервисе
  • Обратная связь
  • Блог

Войдите на сайт

Чтобы задать вопрос и получить на него квалифицированный ответ.
Войти через центр авторизации