Web View
The WebView component is used to display web content within your
application. You use the control by providing a
src
attribute that points at a URL or a local HTML
file.
const webViewModule = require("tns-core-modules/ui/web-view");
import { WebView } from "tns-core-modules/ui/web-view";
Basics
The sample shows a fundamental way of using the WebView in a NativeScript application.
XML
<GridLayout rows="75 * 50">
<GridLayout row="0" rows="*" columns="50 * 50" class="form">
<Button class="btn btn-primary btn-active icon" row="0" col="0" text="" tap="goBack"/>
<TextField row="0" col="1" id="urlField" hint="Enter URL" text="{{ tftext }}" returnKeyType="done" returnPress="submit"
autocorrect="false" verticalAlignment="center" class="input input-border m-t-0" autocapitalizationType="none"/>
<Button class="btn btn-primary btn-active icon" isEnabled="{{ enabled }}" row="0" col="2" text="" tap="goForward"/>
</GridLayout>
<WebView row="1" loaded="onWebViewLoaded" id="myWebView" src="{{ webViewSrc }}" />
<Label row="2" text="{{ result }}" />
</GridLayout>
Add WebView src
and handle
loadFinishedEvent
event
const Observable = require("tns-core-modules/data/observable").Observable;
const dialogs = require("tns-core-modules/ui/dialogs");
const webViewModule = require("tns-core-modules/ui/web-view");
function onNavigatingTo(args) {
const page = args.object;
const vm = new Observable();
vm.set("webViewSrc", "https://docs.nativescript.org/");
vm.set("result", "");
vm.set("tftext", "https://docs.nativescript.org/");
page.bindingContext = vm;
}
// handling WebView load finish event
function onWebViewLoaded(webargs) {
const page = webargs.object.page;
const vm = page.bindingContext;
const webview = webargs.object;
vm.set("result", "WebView is still loading...");
vm.set("enabled", false);
webview.on(webViewModule.WebView.loadFinishedEvent, (args) => {
let message = "";
if (!args.error) {
message = `WebView finished loading of ${args.url}`;
} else {
message = `Error loading ${args.url} : ${args.error}`;
}
vm.set("result", message);
console.log(`WebView message - ${message}`);
});
}
// going to the previous page if such is available
function goBack(args) {
const page = args.object.page;
const vm = page.bindingContext;
const webview = page.getViewById("myWebView");
if (webview.canGoBack) {
webview.goBack();
vm.set("enabled", true);
}
}
// going forward if a page is available
function goForward(args) {
const page = args.object.page;
const vm = page.bindingContext;
const webview = page.getViewById("myWebView");
if (webview.canGoForward) {
webview.goForward();
} else {
vm.set("enabled", false);
}
}
// changing WebView source
function submit(args) {
const page = args.object.page;
const vm = page.bindingContext;
const textField = args.object;
const text = textField.text;
vm.set("enabled", false);
if (text.substring(0, 4) === "http") {
vm.set("webViewSrc", text);
textField.dismissSoftInput();
} else {
dialogs.alert("Please, add `http://` or `https://` in front of the URL string")
.then(() => {
console.log("Dialog closed!");
});
}
}
exports.onNavigatingTo = onNavigatingTo;
exports.onWebViewLoaded = onWebViewLoaded;
exports.submit = submit;
exports.goBack = goBack;
exports.goForward = goForward;
import {Observable} from "tns-core-modules/data/observable";
import * as dialogs from "tns-core-modules/ui/dialogs";
import {WebView, LoadEventData} from "tns-core-modules/ui/web-view";
import { Page } from "tns-core-modules/ui/page";
import { TextField } from "tns-core-modules/ui/text-field";
export function onNavigatingTo(args) {
const page: Page = <Page> args.object;
const vm = new Observable();
vm.set("webViewSrc", "https://docs.nativescript.org/");
vm.set("result", "");
vm.set("tftext", "https://docs.nativescript.org/");
page.bindingContext = vm;
}
// handling WebView load finish event
export function onWebViewLoaded(webargs) {
const page: Page = <Page> webargs.object.page;
const vm = page.bindingContext;
const webview: WebView = <WebView> webargs.object;
vm.set("result", "WebView is still loading...");
vm.set("enabled", false);
webview.on(WebView.loadFinishedEvent, (args: LoadEventData) => {
let message = "";
if (!args.error) {
message = `WebView finished loading of ${args.url}`;
} else {
message = `Error loading ${args.url} : ${args.error}`;
}
vm.set("result", message);
console.log(`WebView message - ${message}`);
});
}
// going to the previous page if such is available
export function goBack(args) {
const page: Page = <Page> args.object.page;
const vm = page.bindingContext;
const webview: WebView = <WebView> page.getViewById("myWebView");
if (webview.canGoBack) {
webview.goBack();
vm.set("enabled", true);
}
}
// going forward if a page is available
export function goForward(args) {
const page: Page = <Page> args.object.page;
const vm = page.bindingContext;
const webview: WebView = <WebView> page.getViewById("myWebView");
if (webview.canGoForward) {
webview.goForward();
} else {
vm.set("enabled", false);
}
}
// changing WebView source
export function submit(args) {
const page: Page = <Page> args.object.page;
const vm = page.bindingContext;
const textField: TextField = <TextField> args.object;
const text = textField.text;
vm.set("enabled", false);
if (text.substring(0, 4) === "http") {
vm.set("webViewSrc", text);
textField.dismissSoftInput();
} else {
dialogs.alert("Please, add `http://` or `https://` in front of the URL string")
.then(() => {
console.log("Dialog closed!");
});
}
}
CSS
.icon{
font-family: 'icomoon';
vertical-align: center;
margin: 6;
}
/*WebView {
border-color: lightgray;
border-width: 0.5;
}*/
Events
The example shows the how to use the events supported by the
WebView component and its reload
method.
<GridLayout rows="50 50 50 *" columns="* *">
<Button row="0" col="0" text="Load first url" tap="loadFirst" />
<Button row="0" col="1" text="Load second url" tap="loadSecond" />
<Button row="1" col="0" colSpan="2" text="Reload page" tap="onReload" />
<Label row="2" col="0" colSpan="2" text="{{ 'Url: ' + webViewSrc }}" textWrap="true" class="p-12" />
<WebView id="webview" row="3" col="0" colSpan="2" loadStarted="onLoadStarted" loadFinished="onLoadFinished" src="{{ webViewSrc }}" />
<GridLayout class="indicator" visibility="{{ isItemVisible ? 'visible' : 'collapsed' }}" row="0" col="0" rowSpan="4" colSpan="2">
<ActivityIndicator width="100" height="100" busy="true"/>
</GridLayout>
</GridLayout>
function onNavigatingTo(args) {
const page = args.object;
const vm = new Observable();
vm.set("webViewSrc", secondUrl);
vm.set("isItemVisible", true);
page.bindingContext = vm;
}
function onLoadStarted(args) {
const page = args.object;
const vm = page.bindingContext;
vm.set("isItemVisible", true);
let message;
if (!args.error) {
message = `WebView started loading of ${args.url}`;
} else {
message = `Error loading ${args.url} : ${args.error}`;
}
console.log(message);
}
function onLoadFinished(args) {
const page = args.object;
const vm = page.bindingContext;
let message;
if (!args.error) {
message = `WebView finished loading of ${args.url}`;
} else {
message = `Error loading ${args.url} : ${args.error}`;
}
console.log(message);
}
function loadFirst(args) {
const page = args.object.page;
const vm = page.bindingContext;
vm.set("webViewSrc", firstUrl);
}
function loadSecond(args) {
const page = args.object.page;
const vm = page.bindingContext;
vm.set("webViewSrc", secondUrl);
}
function onReload(args) {
const page = args.object.page;
webview = page.getViewById("webview");
webview.reload();
}
exports.onNavigatingTo = onNavigatingTo;
exports.onLoadStarted = onLoadStarted;
exports.onLoadFinished = onLoadFinished;
exports.loadFirst = loadFirst;
exports.loadSecond = loadSecond;
exports.onReload = onReload;
export function onNavigatingTo(args) {
const page: Page = <Page>args.object;
const vm = new Observable();
vm.set("webViewSrc", secondUrl);
vm.set("isItemVisible", true);
page.bindingContext = vm;
}
export function onLoadStarted(args) {
const page: Page = <Page>args.object;
const vm = page.bindingContext;
vm.set("isItemVisible", true);
let message;
if (!args.error) {
message = `WebView started loading of ${args.url}`;
} else {
message = `Error loading ${args.url} : ${args.error}`;
}
console.log(message);
}
export function onLoadFinished(args) {
const page = (<Page>args.object);
const vm = page.bindingContext;
let message;
if (!args.error) {
message = `WebView finished loading of ${args.url}`;
} else {
message = `Error loading ${args.url} : ${args.error}`;
}
console.log(message);
}
export function loadFirst(args) {
const page: Page = <Page>args.object.page;
const vm = page.bindingContext;
vm.set("webViewSrc", firstUrl);
}
export function loadSecond(args) {
const page: Page = <Page>args.object.page;
const vm = page.bindingContext;
vm.set("webViewSrc", secondUrl);
}
export function onReload(args) {
const page: Page = <Page>args.object.page;
const webview: WebView = <WebView>page.getViewById("webview");
webview.reload();
}
In the sample code, we set up event loadStarted
and
loadFinished
events. Both events will be fired when
we change the source for the WebView component(change the URL or
load local HTML file). The loadStarted
event will
be executed when the WebView source start loading and
loadFinished
will be fired when the source is
already loaded. The events will return info about the
eventName
, navigationType
and
url
, which we are trying to load. If an error
appears on some of the steps of source load, we will receive the
corresponding error with the error
property in
loadStarted
or loadFinished
events.
In the provided sample, it is also demonstrated how to reload
the currently loaded source via WebView's
reload
method.
Gestures
The code samples show, how we could use gestures in WebView for both platforms iOS and Android.
<GridLayout rows="50 50 *">
<Label row="0" text="{{ touchResult }}" textWrap="true" />
<Label row="1" text="{{ panResult }}" textWrap="true" />
<WebView row="2" loaded="onWebViewLoaded" touch="webViewTouch" pan="webViewPan" src="{{ webViewSrc }}" />
</GridLayout>
function onNavigatingTo(args) {
const page = args.object;
const vm = new Observable();
vm.set("webViewSrc", "<!DOCTYPE html><html><body><h1>My First Heading</h1><p>My first paragraph.</p></body></html>");
vm.set("touchResult", "Touch: x: _ y: _");
vm.set("panResult", "Pan: deltaX: _ deltaY: _");
page.bindingContext = vm;
}
// disabling the WebView's zoom control(required only for Android)
function onWebViewLoaded(webargs) {
const webview = webargs.object;
if (platformModule.isAndroid) {
webview.android.getSettings().setDisplayZoomControls(false);
}
}
// setting up Touch gesture callback method
function webViewTouch(args) {
const page = args.object.page;
const vm = page.bindingContext;
vm.set("touchResult", `Touch: x: ${args.getX().toFixed(3)} y: ${args.getY().toFixed(3)}`);
console.log(`Touch: x: ${args.getX().toFixed(3)} y: ${args.getY().toFixed(3)}`);
}
// setting up Pan gesture callback method
function webViewPan(args) {
const page = args.object.page;
const vm = page.bindingContext;
vm.set("panResult", `Pan: deltaX: ${args.deltaX.toFixed(3)} deltaY: ${args.deltaY.toFixed(3)}`);
console.log(`Pan: deltaX: ${args.deltaX.toFixed(3)} deltaY: ${args.deltaY.toFixed(3)}`);
}
exports.onNavigatingTo = onNavigatingTo;
exports.onWebViewLoaded = onWebViewLoaded;
exports.webViewTouch = webViewTouch;
exports.webViewPan = webViewPan;
export function onNavigatingTo(args) {
const page: Page = <Page>args.object;
const vm = new Observable();
vm.set("webViewSrc", "<!DOCTYPE html><html><body><h1>My First Heading</h1><p>My first paragraph.</p></body></html>");
vm.set("touchResult", "Touch: x: _ y: _");
vm.set("panResult", "Pan: deltaX: _ deltaY: _");
page.bindingContext = vm;
}
// disabling the WebView's zoom control(required only for Android)
export function onWebViewLoaded(webargs) {
const webview: WebView = <WebView>webargs.object;
if (isAndroid) {
webview.android.getSettings().setDisplayZoomControls(false);
}
}
// setting up Touch gesture callback method
export function webViewTouch(args) {
const page: Page = <Page>args.object.page;
const vm = page.bindingContext;
vm.set("touchResult", `Touch: x: ${args.getX().toFixed(3)} y: ${args.getY().toFixed(3)}`);
console.log(`Touch: x: ${args.getX().toFixed(3)} y: ${args.getY().toFixed(3)}`);
}
// setting up Pan gesture callback method
export function webViewPan(args) {
const page: Page = <Page>args.object.page;
const vm = page.bindingContext;
vm.set("panResult", `Pan: deltaX: ${args.deltaX.toFixed(3)} deltaY: ${args.deltaY.toFixed(3)}`);
console.log(`Pan: deltaX: ${args.deltaX.toFixed(3)} deltaY: ${args.deltaY.toFixed(3)}`);
}
Note: to be able to use gestures in
WebView
component on Android, we should first disabled the zoom control. To do that we could access theandroid
property and with the help ofsetDisplayZoomControls
to set this control tofalse
.
Source Load
The example demonstrates, how to load content in the WebView
component, while using a local file or while providing HTML code
directly to its src
property.
XML
<GridLayout rows="100 50 * 50" columns="*">
<WebView row="0" col="0" loaded="onFirstWebViewLoaded" src="{{ firstWebViewSRC }}"/>
<Label row="1" text="{{ resultFirstWebView }}" textWrap="true" />
<WebView row="2" col="0" loaded="onSecondWebViewLoaded" src="{{ secondWebViewSRC }}"/>
<Label row="3" text="{{ resultSecondWebView }}" textWrap="true" />
</GridLayout>
Add WebView src
from local file. You might need to
add a glob for your HTML paths to the copy plugin in
webpack.config.js. e.g.
new CopyWebpackPlugin([ { from: { glob: "www/*.html" }
}]
const Observable = require("tns-core-modules/data/observable").Observable;
const webViewModule = require("tns-core-modules/ui/web-view");
function onNavigatingTo(args) {
const page = args.object;
const vm = new Observable();
// loading the WebView source while providing a HTML code
vm.set("firstWebViewSRC", "<!DOCTYPE html><html><head><title>MyTitle</title><meta charset='utf-8' /></head><body><span style='color:#0099CC; text-align: center;'>First WebView</span></body></html>");
vm.set("resultFirstWebView", "");
// loading the WebView source from a local file
vm.set("secondWebViewSRC", "~/ns-ui-widgets-category/web-view/source-load/test.html");
vm.set("resultSecondWebView", "");
page.bindingContext = vm;
}
function onFirstWebViewLoaded(webargs) {
const page = webargs.object.page;
const vm = page.bindingContext;
const webview = webargs.object;
vm.set("resultFirstWebView", "First WebView is still loading...");
// handling WebView load finish event
webview.on(webViewModule.WebView.loadFinishedEvent, (args) => {
let message = "";
if (!args.error) {
message = `First WebView finished loading of ${args.url}`;
} else {
message = `Error loading first WebView ${args.url} : ${args.error}`;
}
vm.set("resultFirstWebView", message);
console.log("First WebView message - ", message);
});
}
function onSecondWebViewLoaded(webargs) {
const page = webargs.object.page;
const vm = page.bindingContext;
const webview = webargs.object;
vm.set("resultSecondWebView", "Second WebView is still loading...");
webview.on(webViewModule.WebView.loadFinishedEvent, (args) => {
let message = "";
if (!args.error) {
message = `Second WebView finished loading of ${args.url}`;
} else {
message = `Error loading second WebView ${args.url} : ${args.error}`;
}
vm.set("resultSecondWebView", message);
console.log("Second WebView message - ", message);
});
}
exports.onNavigatingTo = onNavigatingTo;
exports.onFirstWebViewLoaded = onFirstWebViewLoaded;
exports.onSecondWebViewLoaded = onSecondWebViewLoaded;
import {Observable} from "tns-core-modules/data/observable";
import {WebView, LoadEventData} from "tns-core-modules/ui/web-view";
import {Page} from "tns-core-modules/ui/page";
export function onNavigatingTo(args) {
const page: Page = <Page> args.object;
const vm = new Observable();
// loading the WebView source while providing a HTML code
vm.set("firstWebViewSRC", "<!DOCTYPE html><html><head><title>MyTitle</title><meta charset='utf-8' /></head><body><span style='color:#0099CC; text-align: center;'>First WebView</span></body></html>");
vm.set("resultFirstWebView", "");
// loading the WebView source from a local file
vm.set("secondWebViewSRC", "~/ns-ui-widgets-category/web-view/source-load/test.html");
vm.set("resultSecondWebView", "");
page.bindingContext = vm;
}
export function onFirstWebViewLoaded(webargs) {
const page: Page = <Page> webargs.object.page;
const vm = page.bindingContext;
const webview: WebView = <WebView> webargs.object;
vm.set("resultFirstWebView", "First WebView is still loading...");
// handling WebView load finish event
webview.on(WebView.loadFinishedEvent, (args: LoadEventData) => {
let message = "";
if (!args.error) {
message = `First WebView finished loading of ${args.url}`;
} else {
message = `Error loading first WebView ${args.url} : ${args.error}`;
}
vm.set("resultFirstWebView", message);
console.log("First WebView message - ", message);
});
}
export function onSecondWebViewLoaded(webargs) {
const page: Page = <Page> webargs.object.page;
const vm = page.bindingContext;
const webview: WebView = <WebView>webargs.object;
vm.set("resultSecondWebView", "Second WebView is still loading...");
webview.on(WebView.loadFinishedEvent, (args: LoadEventData) => {
let message = "";
if (!args.error) {
message = `Second WebView finished loading of ${args.url}`;
} else {
message = `Error loading second WebView ${args.url} : ${args.error}`;
}
vm.set("resultSecondWebView", message);
console.log("Second WebView message - ", message);
});
}
API Reference for the WebView Class
Native Component
Android | iOS |
---|---|
android.webkit.WebView | WKWebView |