I have a directive which adds an icon to whatever element it is added to. When that icon is clicked, I need to call a function in whatever component contains the directive. This function uses router.navigate
to navigate a named-outlet to a new component. Everything works, except that after I click the icon, the new contents of the named router outlet don't show until I move my mouse.
Here are the relevant parts of the directive:
@Directive({
selector: '[editable]',
})
...
@Output() doEdit = new EventEmitter<string>();
...
private emitEditMessage(){
console.log("emitting"); <-----just so I can see that the function is called
this.doEdit.emit(this.targetField);
}
Here is where I use the directive in a template:
<span editable (doEdit)="editField($event)">
{{CurrentPersonInfo}}
</span>
Here is the function from my parent component that is called when the directive emits:
public editField(fldName :string){
console.log("before nav");
this.router.navigate([{ outlets: { 'task-pane': 'edit' } }]);
console.log("after nav");
}
When I run and click on the icon shown by the directive, I see the expected messages in the console: "emitted", "before nav", "after nav". But the secondary route ("name:task-pane") doesn't update with the new contents until I move the mouse.
Update: Just noticed this: if the content in the task pane is just a hard-coded string, then it is shown immediately. However, if I add an interpolated binding to a property of the task pane component (e.g {{Title}} ) then any hard-coded text before the binding shows immediately. The bound text and any hard-coded text after it doesn't show up until I move the mouse.
Here is the panel component:
@Component({
...
})
export class PersonEditPanelComponent extends BasePanel{
constructor(){
super();
console.log("panel ctor");
}
public Title: string = "Edit Person"
}
Here is the panel template HTML:
This shows immediately.
{{Title}}
This and the "Title" won't show until I move the mouse after clicking the icon
Finally, if I put a link on my parent component that just directly calls its editField
function (the same one called when the directive emits), then everything works - all text (hard-coded and bound) shows immediately.
So, my questions: Is there something inherent in the routing that is causing this delay for bindings being resolved? Any idea how to fix this?
Thanks!
Solved. I took a different approach to attaching the event listener and got it all working. Here are the details:
Injected Renderer2
via the constructor on my directive:
constructor(elem: ElementRef, private renderer: Renderer2, private router: Router)
{}
Then after the code that added the icon into the page, I attached the listener like this:
this.renderer.listen(this.editIcon, 'click', (evt) => {
this.doEdit.emit(this.targetField);
});
Where editIcon
is the DOM element I created and added:
private editIcon = document.createElement('a');
this.editIcon.innerHTML = '<i class="fa fa-pencil" aria-hidden="true" style="font-size:18px; color:red;"></i>';
node.appendChild(this.editIcon);