0

I am attempting to create a service which handles some custom floating action buttons. My aim is to be able to either define the buttons in the HTML of a component, as well as, add, modify, update and delete them dynamically using an injectable service.

The following code works when navigating to the page directly using the address bar. It doesn't work, however, when navigating to the same page using links (with [routerLink]).

@Injectable()
export class ActionButtonService {

    constructor( private element: ElementRef ) {
    }

    private container: HTMLElement;

    private getContainer = function getContainer(){
        if ( this.container == null ) {
            let foundContainer = document.getElementById( "actions" );
            if ( foundContainer != null ) {
                this.container = foundContainer;
            } else {
                let createdContainer = document.createElement( "div");
                createdContainer.setAttribute( "id", "actions" );
                this.element.nativeElement.parentElement.appendChild( createdContainer );
                this.container = createdContainer;
            }
        }

        return this.container;
    }

    public addAction = function( icon: string, title: string, onclick, id: string = null ) {
        let container = this.getContainer();

        let newButton = document.createElement( "a" );
        newButton.title = title;
        if ( id != null ) newButton.id = id;
        newButton.innerHTML = "<md-icon class=\"material-icons mat-icon\">"+ icon +"</md-icon>";
        newButton.onclick = onclick;
        container.appendChild( newButton );
    }
}

When navigating directly to the page, I can see the #actions element. When magnifying through the use of links, the #actions element is nowhere to be seen.

Is there a better, more reliable way to go about adding these kinds of buttons dynamically? I'd need the buttons to be in the root component (currently active route), so that they get swapped out correctly when navigating the UI and so that I'm able to define the buttons within the HTML of each component.

Josh-Mason
  • 319
  • 3
  • 8
  • 22
  • "it doesn't work" provides no explanation of what the problem is. – Reactgular Aug 02 '17 at 17:49
  • Thank you for your quick response. I have added a little extra information; hopefully that helps. I don't have a very deep understanding of how routing works, do I thought maybe it's something to do with that. It's difficult to explain and I apologise for this – Josh-Mason Aug 02 '17 at 18:01

2 Answers2

0

You probably don't actually want to do it this way.

I'm not sure I grasp your requirements. The only reason I can think of to insert the buttons dynamically is if you are allowing your users to define buttons, which seems unlikely, and possibly really bad practice if you are allowing them to insert javascript code into the onclick.

Do you have a finite set of buttons? Why wouldn't you just create a component that holds all the buttons and then use *ngIf to determine whether they actually render or not?

yanbu
  • 183
  • 8
  • The buttons can be pretty much anything and there will be a lot of them. The use case for the dynamic control is that I have a stepper. The stepper needs a back and forward button. For consistency, these should look the same as other primary actions and therefore will need to use the same styling and properties. The way I define the actions for the stepper is different because I can't define them outside of the stepper element (where I define the main actions) whilst sticking to DRY principles – Josh-Mason Aug 02 '17 at 18:46
0

This is a very very bad idea to create button and div this way , you must not modify the DOM , like you are doing.

but you should do as follow :

  • define a ButtonComponent class
  • define it as an entryComponent in app.module.ts file

  • then to create some components dynamically, use next code :

    let factory = this.componentFactoryResolver.resolveComponentFactory(ButtonComponent); this.componentRef = this.other.createComponent(factory);

have a look at this link : How to place a dynamic component in a container

sancelot
  • 1,905
  • 12
  • 31
  • Thank you for your suggestion. I will look into implementing it and let you know how it went. (Sorry for the late response; I have been struggling with compilation issues in angular cli) – Josh-Mason Aug 04 '17 at 11:48