How to bind custom WKWebView element with ElementRef?


#1

I looked here one example and based on it make my own NativeScript WKWebView plugin for iOS. Seems everything works, no errors. But I don’t know how to bind this element to a WKWebView which is in the html template.

// Plugin code: wkwebview.ios.ts
import {View} from 'ui/core/view';

declare const NSURL: any;
declare const NSURLRequest: any;
declare const WKNavigationDelegate: any;
declare const WKWebView: any;

class NSWKNavigationDelegate extends NSObject implements WKNavigationDelegate {
    static ObjCProtocols = [WKNavigationDelegate];
    private _owner: WeakRef<NSWKWebView>;

    static initWithOwner(owner: WeakRef<NSWKWebView>): NSWKNavigationDelegate {
        const delegate = <NSWKNavigationDelegate>NSWKNavigationDelegate.new();
        delegate._owner = owner;
        return delegate;
    }

    didStartProvisionalNavigation(webView: WKWebView, navigation: WKNavigation) {
        console.log('didStartProvisionalNavigation');
    }

    didFinishNavigation(webView: WKWebView, navigation: WKNavigation) {
        console.log('didFinishNavigation');
    }

    didFailNavigationWithError(webView: WKWebView, navigation: WKNavigation, error: NSError) {
        console.log('didFailNavigationWithError');
    }

    decidePolicyForNavigationActionDecisionHandler(webView: WKWebView, navigationAction: WKNavigationAction, decisionHandler: WKNavigationActionPolicy) {
        console.log('decidePolicyForNavigationActionDecisionHandler');
    }
}

export class NSWKWebView extends View {
    get ios(): WKWebView {
        return this._ios;
    }

    private _ios: WKWebView;
    private _navigationDelegate: any;

    constructor() {
        super();

        this._ios = WKWebView.new();
        this._navigationDelegate = NSWKNavigationDelegate.initWithOwner(new WeakRef(this));
    }

    viewDidLoad() {
        console.log('viewDidLoad');
    }

    loadUrl(url: string) {
        console.log('loadUrl');
        this._ios.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(url)));
    }

    userContentController(userContentController: WKUserContentController, scriptMessage: WKScriptMessage) {
        const dict: any = scriptMessage;
        const username: string = dict.username;
        const secretToken: string = dict.sectetToken;

        this._ios.evaluateJavaScriptCompletionHandler('window.setValue(\'Kamon\')', (res, err) => {
            if (err) {
                console.log('Error evaluateJavaScriptCompletionHandler: ', err);
            } else {
                console.log('Success evaluateJavaScriptCompletionHandler.');
            }
        });
    }

    onUnloaded() {
        console.log('onUnloaded');
        this._ios.navigationDelegate = null;
        super.onUnloaded();
    }
}
// Demo code: webview.component.ts
import {Component, OnInit, AfterViewInit, OnDestroy, ViewChild, ElementRef, ChangeDetectorRef} from '@angular/core';
import {registerElement} from 'nativescript-angular/element-registry';

const NSWKWebView = require('nativescript-wkwebview').NSWKWebView;

registerElement('WKWebView', () => NSWKWebView);

@Component({
    moduleId: module.id,
    selector: 'webview',
    templateUrl: 'webview.component.html'
})
export class WebViewComponent implements OnInit, AfterViewInit, OnDestroy {
    @ViewChild('webView') webView: ElementRef;

    private wkWebView = new NSWKWebView();

    constructor(private changeDetectorRef: ChangeDetectorRef) {
    }

    ngOnInit(): void {

    }

    ngAfterViewInit(): void {
        this.wkWebView.loadUrl('https://www.google.com');
        this.wkWebView.onLoaded();
    }

    ngOnDestroy(): void {

    }
}
// Demo code: wkwebview.component.html
<StackLayout>
    <WKWebView id="WKWebView"></WKWebView>
</StackLayout>

When I call this.wkWebView.loadUrl(‘https://www.google.com’), the console displays the ‘loadUrl’, it means that the function works. But I don’t understand how to load google.com in WKWebView wich in the template :frowning: I know that I need to bind this.webView and this.wkWebView, but how?..


#2

I solved this issue by:

ngAfterViewInit(): void {
    this.webView.nativeElement.loadUrl('~/www/index.html');
    this.webView.nativeElement.onLoaded();
}