1

I'm new to Angular and part of my problem is that I don't know what exactly this falls under, so I don't know where to research.

I'm building a save button component. This exists 10+ times throughout our app and has the same look and location in each view. The save function, however, will be a little different and might require some unique form validation based on where you're clicking it from.

The save button component is super lean at the moment and uses Angular Material.

import * as save from './buttonSave';

import './buttonSave.component.less';

@save.Component({
    selector: 'ui-buttonSave',
    template:
`
<button md-fab color="accent">
   <md-icon class="md-24">save</md-icon>
</button>
`,
    directives: [save.MdButton, save.MdIcon],
    viewProviders: [save.MdIconRegistry]
})

export class ButtonSaveComponent {

}

What I would like to do is include a default click behavior that routes to some local save function located in the parent component that uses this save component in the template. To use this save button component, all I'd need to do (in theory) is stick it in the template, import/list the directives (maybe list a provider?), and then overwrite the save function for that component (maybe it could be called saveClick or something).

I don't really know what this would use in Angular to achieve this... EventEmitter? Output? Provider?

I know I could sidestep this by just doing this whenever I use this save component...

<ui-buttonSave (click)="localSave($event)"></ui-buttonSave>

But I would rather use all of the bells and whistles that Angular gives me. Any direction/help is greatly appreciated!

sup bro
  • 261
  • 8
  • 18

2 Answers2

1

It looks like you are creating a reusable UI component, hence the save action/behavior should not (cannot) be part of that component. Trying to override an (abstract) "save" component function is more of an object-oriented design approach, rather than an Angular component approach (which is to emit an event when some user action occurs).

So, I suggest you delegate the save action/behavior to the parent, like you mentioned, either by binding to the existing DOM click event:

<ui-buttonSave (click)="save($event)"></ui-buttonSave>

or define and bind to a custom event (which would require an EventEmitter):

<ui-buttonSave (saveRequested)="save($event)"></ui-buttonSave>

Regarding validating user input, here's something to consider from the documentation: https://angular.io/docs/ts/latest/guide/architecture.html#!#services

We prefer our component classes lean. Our components don't fetch data from the server, they don't validate user input, and they don't log directly to the console. They delegate such tasks to services.

Mark Rajcok
  • 348,511
  • 112
  • 482
  • 482
0

you can override the 3rd party component functionality using a directive

<button md-fab color="accent" someDirective>
   <md-icon class="md-24">save</md-icon>
</button>

create Directive used in button

import { Directive } from '@angular/core';
import { Host, Self, Optional } from '@angular/core';

@Directive({
    selector: '[someDirective]',
})
export class SomeDirectiveDirective {
    
    constructor(
      @Host() @Self() @Optional() public hostSel : Select) {
      // Now you can access specific instance members of host directive
      let app = (<any>hostSel)._app;
      // also you can override specific methods from original host directive so that this specific instance uses your method rather than their original methods.
      hostSel.click= (ev?: UIEvent) => {
        // your custom code for save() method here..
      }
    }
}

https://medium.com/angular-in-depth/changing-the-behavior-of-a-3rd-party-angular-component-91f84fb9af28

jen
  • 51
  • 6