Components: Inherit/Extend angular material components

Created on 1 Mar 2018  路  11Comments  路  Source: angular/components

Use case: I want to disable a specific animation in the select component (the @transformPanel animation), in order to do so i just need to override the template or the animation property of the components annotation, or to copy the whole MatSelect component to my project / fork Angular Material and to maintain it or to write my own component in CDK. #2194 #9216

Angular still doesn't support Annotation/Metadata inheritance, but there where some links to the new Ivy Renderer / Angular v6 Compiler.

CDK is nice but to construct a select component to be as good as the MatSelect component is a lot of work, we used to copy the code from the original MatSelect component but it's hard to maintain it with Material/CDK updates.

Solving this problem would allow end-developer to reimplement individual functions of the base class/component the best example is the new disableOptionCentering property - it won't be needed because the end-developer could do it easily.

Any best practice or under development for this case ?

Most helpful comment

+1

All 11 comments

One solution to this problem is the following, so i can define my own animation or disable it in ./select-animations.ts or in the custom .html file. But it would be much much better if the @Component annotation could be inherited, the code would be much more clear.
Should there be some official documentation for it in the angular material docs ?

See also:
[Miskos comment](https://github.com/angular/angular/issues/7968#issuecomment-219865739 )

    import { ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
    import { MAT_OPTION_PARENT_COMPONENT } from '@angular/material/core';
    import { MatFormFieldControl } from '@angular/material/form-field';

    import { MatSelect } from '@angular/material';
    import { matSelectAnimations } from './select-animations';

    @Component({
        moduleId: module.id,
        selector: 'ab-select',
        exportAs: 'abSelect',
        templateUrl: 'select.component.html',
        inputs: ['disabled', 'disableRipple', 'tabIndex'],
        encapsulation: ViewEncapsulation.None,
        preserveWhitespaces: false,
        changeDetection: ChangeDetectionStrategy.OnPush,
        host: {
            'role': 'listbox',
            '[attr.id]': 'id',
            '[attr.tabindex]': 'tabIndex',
            '[attr.aria-label]': '_ariaLabel',
            '[attr.aria-labelledby]': 'ariaLabelledby',
            '[attr.aria-required]': 'required.toString()',
            '[attr.aria-disabled]': 'disabled.toString()',
            '[attr.aria-invalid]': 'errorState',
            '[attr.aria-owns]': 'panelOpen ? _optionIds : null',
            '[attr.aria-multiselectable]': 'multiple',
            '[attr.aria-describedby]': '_ariaDescribedby || null',
            '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',
            '[class.mat-select-disabled]': 'disabled',
            '[class.mat-select-invalid]': 'errorState',
            '[class.mat-select-required]': 'required',
            'class': 'mat-select',
            '(keydown)': '_handleKeydown($event)',
            '(focus)': '_onFocus()',
            '(blur)': '_onBlur()',
        },
        animations: [
            matSelectAnimations.fadeInContent,
            matSelectAnimations.transformPanel
        ],
        providers: [
            { provide: MatFormFieldControl, useExisting: AbSelect },
            { provide: MAT_OPTION_PARENT_COMPONENT, useExisting: AbSelect }
        ],
    })
    export class AbSelect extends MatSelect {}

Please keep GitHub issues for bug reports / feature requests. Better avenues for troubleshooting / questions are stack overflow, gitter, mailing list, etc.

Were you able to ended the components in the end without duplicate code that already existed in the library? I tried to "extend" the card component but it isn't as simple as my-mat-card extend mat-card.

You have to look a lot at the sourcecode of the component. The bad thing is rlthat almost everyting is private and not protected.
Another solution is to fork the project on github and to maintain your version but i think this is more overhead than just to extend the component.

I believe this should be considered as a feature request.

+1

Actually, it would be so adorable to have this kind of feature...

Yeah I spent days looking to extend a component, but as someone mentioned everything is private , it would be nice to be able to extend because a lot of the component don't fit our use scenario and not being able to extend is definitely a big problem for us.

Could always fork and change everything to protected

Could always fork and change everything to protected

I thought of that too but I don't know if we want to do that, I will have to consult with my team lead.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RoxKilly picture RoxKilly  路  3Comments

constantinlucian picture constantinlucian  路  3Comments

Miiekeee picture Miiekeee  路  3Comments

savaryt picture savaryt  路  3Comments

jelbourn picture jelbourn  路  3Comments