1

I'm using mdl-select component. It's a drop-down list. When you press it there are focusin event fired. But it doesn't when you press an arrow-dropdown icon, so I needed to change a template a bit to have a desired behavior. But it's a library component. Is there a way to override it's template?

The thing I need to change just to add tabindex=\"-1\" to element. I can do it with js, but I use component a lot in app, and I don't want to use document.getElement... every time I use MdlSelectComponent in the views of my own components.

I tried to use @Component decorator function on MdlSelectComponent type, however it requires to declare this class once again and anyway have done nothing.

Update

main.browser.ts

/*
 * Angular bootstraping
 */
import { Component } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { decorateModuleRef } from './app/environment';
import { bootloader } from '@angularclass/hmr';

import {MdlSelectComponent} from '@angular2-mdl-ext/select';
/*
 * App Module
 * our top level module that holds all of our components
 */
import { AppModule } from './app';

/*
 * Bootstrap our Angular app with a top level NgModule
 */
export function main(): Promise<any> {
  console.log(MdlSelectComponent)
  MdlSelectComponent.decorator.template = "<div class=\"mdl-textfield is-upgraded\" [class.is-focused]=\"this.popoverComponent.isVisible || this.focused\" [class.is-disabled]=\"this.disabled\" [class.is-dirty]=\"isDirty()\"> <span [attr.tabindex]=\"!this.disabled ? 0 : null\" (focus)=\"open($event);addFocus();\" (blur)=\"removeFocus()\"> <!-- don't want click to also trigger focus --> </span> <input #selectInput tabindex=\"-1\" [readonly]=\"!autocomplete\" class=\"mdl-textfield__input\" (click)=\"toggle($event)\" (keyup)=\"onInputChange($event)\" (blur)=\"onInputBlur()\" [placeholder]=\"placeholder ? placeholder : ''\" [attr.id]=\"textfieldId\" [value]=\"text\"> <span class=\"mdl-select__toggle material-icons\" (click)=\"toggle($event)\"> keyboard_arrow_down </span> <label class=\"mdl-textfield__label\" [attr.for]=\"textfieldId\">{{ label }}</label> <span class=\"mdl-textfield__error\"></span> <mdl-popover [class.mdl-popover--above]=\"autocomplete\" hide-on-click=\"!multiple\" [style.width.%]=\"100\"> <div class=\"mdl-list mdl-shadow--6dp\"> <ng-content></ng-content> </div> </mdl-popover> </div> ";

  return platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .then(decorateModuleRef)
    .catch((err) => console.error(err));
}

// needed for hmr
// in prod this is replace for document ready
bootloader(main);

APP.COMPONENT.TS

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Router } from '@angular/router';
require('../../../styles/styles.scss');
import {MdlSelectComponent} from '@angular2-mdl-ext/select';
//
declare let Reflect: any;
Reflect.getOwnMetadata('annotations', MdlSelectComponent)[0].template = 'Hooray';
@Component({
    selector: 'app',
    encapsulation: ViewEncapsulation.None,
    styleUrls: [],
    template: `
        <div>
            <mdl-select [(ngModel)]="personId">
                <mdl-option *ngFor="let p of people" [value]="p.id">{{p.name}}</mdl-option>
            </mdl-select>
            <router-outlet></router-outlet>
        </div>`
})
export class AppComponent implements OnInit {
    constructor(
        router: Router,
    ) {
        router.events.subscribe(data => {
            scrollTo(0, 0);
        });
    }

    public ngOnInit() {
    }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
K.Rice
  • 599
  • 1
  • 8
  • 27
  • You can copy paste the component with your own name and add the functionality you desire. SInce you are using angular2-mdl it should be very easy – Vamshi Jul 05 '17 at 11:24
  • @Skeptor Peatifully, it's not an option. Component uses a lot of inner library dependences, and it's not a single component from the library I use. As a case I can override that file with a help of webpack, but I wanted to know if I can just redecorate it with a new template for example in `app.component.ts`/ – K.Rice Jul 05 '17 at 12:02
  • Try if you can do something like `MdlSelectComponent.decorator.template =''` inside `main.ts`. Since its all mdl , you can write your own html with appropriate classes just for that component and build your own component – Vamshi Jul 05 '17 at 12:33
  • @Skeptor Have done this (see update) but is says there'is no decorator property on this type. Am I doing something wrong? – K.Rice Jul 05 '17 at 13:06

1 Answers1

2

As @angular2-mdl-ext/select uses Reflect to define decorators then you do the following

declare let Reflect: any;
Reflect.getOwnMetadata('annotations', MdlSelectComponent)[0].template = 'Hooray';

Plunker Example

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • Hi, thanks you very mush for replay. I've inserted the following lines in my `app.module.ts` file as you did in planker, however still can't get it to work - template doesn't change( Have tried with `main.ts` and `app.component.ts` as well. You can see `app.component.ts` in updates. What have I done wrong? – K.Rice Jul 05 '17 at 14:45
  • @K.Rice How do you build your project? Maybe you can put up a github repo with minimal reproduction? – yurzui Jul 05 '17 at 14:49
  • Thanks for repo. You are overriding another component with the same name `import { MdlSelectComponent } from '@angular2-mdl-ext/select';` – yurzui Jul 05 '17 at 15:33
  • But you use component from `import { MdlSelectModule, MdlSelectComponent } from '@angular-mdl/select';` – yurzui Jul 05 '17 at 15:34
  • So remove `import { MdlSelectComponent } from '@angular2-mdl-ext/select';` and import `MdlSelectComponent` from `@angular-mdl/select` – yurzui Jul 05 '17 at 15:35
  • Oh, I see. Replaced with a proper component and now works. Thanks a lot! – K.Rice Jul 05 '17 at 15:39
  • Glad to hear! :) – yurzui Jul 05 '17 at 15:41