Reputation: 914
I've an Ionic 2 application that pulls some HTML content from a REST service. That content is shown to the user as usual HTML content: parragraphs, rich text, etc.
Some links in the content, when clicked, should make the app to show a new app page (that's push a Page in the NavController).
With fixed content inside the app this is very easy:
In template
Bla bla bla <a href="/specialPage/someId" (click)="pushSpecialPage($event, 'someId')">link text</a> bla bla bla.
In component class:
pagePush(event, destiny: string) {
this.navCtrl.push(SpecialPage, { contentId: destiny });
}
}
Given that SpecialPage
is an ionic 2 page component.
The problem is that my content comes from a service and when I insert it using [innerHTML]=
content is not processed as Angular2 content.
So, how I cant react to clicks in content pulled using a service?
My thoughts are:
Detect links that should be processed and add angular code to them to react (probably (click)
) and then compile somehow the code and insert it into the template.
Use a custom protocol (for example, href="specialPage://someId") and intercept user clicks on those links. Once the click is intercepted by Angular2, push the proper Page to the NavController.
I don't know if any of those approaches are valid and how to implement them. I've doubts about first solution because reading Angular 2 blog post Angular 2 RC5 - NgModules, Lazy Loading and AoT compilation it's said:
From the beginning, part of the design for Angular 2 was to enable this process to happen Ahead of Time (AoT) - that is, as a build step, when building your application. Roughly 60% of Angular’s code size is the compiler which does this work, so enabling AoT compilation means you don’t have to ship that code to your users, which gives a huge savings in bytes over the wire.
It seems no compiler code is pushed to he client, so it's not possible to compile on the fly.
Upvotes: 1
Views: 492
Reputation: 914
The solution is to apply a click listener to the component. The handler should check if clicked element is an anchor and the href points to an internal page. If yes, call NavController.
For example, say that you know that all links in the form href="/myInternalPage/pageId"
should point to an internal app page.
In your component import ElementRef
and Rederer
. Then, using both, set up a click listener:
constructor(public navCtrl: NavController,
elementRef: ElementRef,
renderer: Renderer) {
// Listen to click events in the component
renderer.listen(elementRef.nativeElement, 'click', (event) => {
var rc: boolean = true;
if (event.target.nodeName == 'A') {
rc = this.processClickOnATag(event.target.href);
}
return rc;
})
}
Now every click is processed by the processClickOnATag
function.
The handler code:
processClickOnATag(href: string): boolean {
var rc: boolean = true;
var pos: number;
if ((pos = href.indexOf('/myInternalPage/')) !== -1) {
rc = this.processClickOnSpecialPageLink(href.substring(pos))
}
return rc;
}
The return code is needed to cancel event bubbling (if not WebView will try yo follow the link, breaking the app).
Finally, the processClickOnSpecialPageLink function code:
private processClickOnSpecialPageLink(pageRef: string): boolean {
var rc: boolean = true;
var refParts = pageRef.split('/');
// Check this is actually an special page.
if (refParts[1] === 'myInternalPage') {
this.navCtrl.push(MySpecialPage, { pageId: refParts[2]});
rc = false;
}
return rc;
}
You can add special properties to your links to avoid processing the href (prone to errors). For example, you can add data-special-page="specialPageId"
so you can detect special page links inmediatly (does the a
tag have the data-special-page attribute
?) and have the id in just one attribute.
Upvotes: 1