diff --git a/apps/nativescript-demo-ng/src/app/app.routes.ts b/apps/nativescript-demo-ng/src/app/app.routes.ts
index 2ed3853..3099fef 100644
--- a/apps/nativescript-demo-ng/src/app/app.routes.ts
+++ b/apps/nativescript-demo-ng/src/app/app.routes.ts
@@ -2,6 +2,7 @@ import { Routes } from '@angular/router';
import { ItemDetailComponent } from './item/item-detail.component';
import { ItemsComponent } from './item/items.component';
import { ListViewStickyComponent } from './list-view-sticky/list-view-sticky.component';
+import { SPLIT_VIEW_ROUTES } from './split-view-demo/split-view.routes';
// import { HomeComponent } from './home/home.component';
// import { BootGuardService } from './boot-guard.service';
@@ -15,6 +16,10 @@ export const routes: Routes = [
path: 'list-view-sticky',
component: ListViewStickyComponent,
},
+ {
+ path: 'split-view-demo',
+ children: SPLIT_VIEW_ROUTES,
+ },
/**
* Test tab named outlets
diff --git a/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-demo.component.html b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-demo.component.html
new file mode 100644
index 0000000..ad72418
--- /dev/null
+++ b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-demo.component.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-demo.component.ts b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-demo.component.ts
new file mode 100644
index 0000000..6a0a561
--- /dev/null
+++ b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-demo.component.ts
@@ -0,0 +1,52 @@
+import { Component, inject, NO_ERRORS_SCHEMA, OnInit, AfterViewInit } from '@angular/core';
+import {
+ NativeScriptCommonModule,
+ NativeScriptRouterModule,
+ PageRouterOutlet,
+ RouterExtensions,
+} from '@nativescript/angular';
+import { SplitViewState } from './split-view.state';
+
+@Component({
+ selector: 'ns-split-view-demo',
+ templateUrl: './split-view-demo.component.html',
+ imports: [NativeScriptCommonModule, NativeScriptRouterModule, PageRouterOutlet],
+ schemas: [NO_ERRORS_SCHEMA],
+})
+export class SplitViewDemoComponent implements OnInit, AfterViewInit {
+ router = inject(RouterExtensions);
+ splitViewState = inject(SplitViewState);
+
+ ngOnInit() {
+ console.log('[SplitViewDemo] ngOnInit');
+ }
+
+ ngAfterViewInit() {
+ console.log('[SplitViewDemo] ngAfterViewInit - view is initialized, navigating to outlets');
+ // Use setTimeout to ensure the view is fully rendered and outlets are registered
+ setTimeout(() => {
+ console.log('[SplitViewDemo] Navigating to outlets...');
+ this.router
+ .navigate(
+ [
+ '/',
+ {
+ outlets: {
+ primary: ['primary'],
+ secondary: ['secondary'],
+ supplementary: ['supplementary'],
+ inspector: ['inspector'],
+ },
+ },
+ ],
+ { animated: false },
+ )
+ .then((success) => {
+ console.log(`[SplitViewDemo] navigation result: ${success}`);
+ })
+ .catch((err) => {
+ console.error(`[SplitViewDemo] navigation error: ${err}`);
+ });
+ }, 0);
+ }
+}
diff --git a/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-inspector.component.ts b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-inspector.component.ts
new file mode 100644
index 0000000..0e055d4
--- /dev/null
+++ b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-inspector.component.ts
@@ -0,0 +1,44 @@
+import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
+import { NativeScriptCommonModule } from '@nativescript/angular';
+
+@Component({
+ selector: 'ns-split-view-inspector',
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ imports: [NativeScriptCommonModule],
+ schemas: [NO_ERRORS_SCHEMA],
+})
+export class SplitViewInspectorComponent {}
diff --git a/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-primary.component.ts b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-primary.component.ts
new file mode 100644
index 0000000..a663614
--- /dev/null
+++ b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-primary.component.ts
@@ -0,0 +1,57 @@
+import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
+import { NativeScriptCommonModule } from '@nativescript/angular';
+
+@Component({
+ selector: 'ns-split-view-primary',
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ imports: [NativeScriptCommonModule],
+ schemas: [NO_ERRORS_SCHEMA],
+})
+export class SplitViewPrimaryComponent {}
diff --git a/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-secondary.component.ts b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-secondary.component.ts
new file mode 100644
index 0000000..047cd5a
--- /dev/null
+++ b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-secondary.component.ts
@@ -0,0 +1,98 @@
+import { Component, inject, NO_ERRORS_SCHEMA } from '@angular/core';
+import { NativeScriptCommonModule } from '@nativescript/angular';
+import { SplitViewState } from './split-view.state';
+
+@Component({
+ selector: 'ns-split-view-secondary',
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @if (!splitViewState.inspectorVisible()) {
+
+
+
+
+ }
+
+
+
+ `,
+ imports: [NativeScriptCommonModule],
+ schemas: [NO_ERRORS_SCHEMA],
+})
+export class SplitViewSecondaryComponent {
+ splitViewState = inject(SplitViewState);
+}
diff --git a/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-supplementary.component.ts b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-supplementary.component.ts
new file mode 100644
index 0000000..ec085dc
--- /dev/null
+++ b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view-supplementary.component.ts
@@ -0,0 +1,64 @@
+import { Component, NO_ERRORS_SCHEMA } from '@angular/core';
+import { NativeScriptCommonModule } from '@nativescript/angular';
+
+@Component({
+ selector: 'ns-split-view-supplementary',
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ imports: [NativeScriptCommonModule],
+ schemas: [NO_ERRORS_SCHEMA],
+})
+export class SplitViewSupplementaryComponent {}
diff --git a/apps/nativescript-demo-ng/src/app/split-view-demo/split-view.routes.ts b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view.routes.ts
new file mode 100644
index 0000000..db72531
--- /dev/null
+++ b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view.routes.ts
@@ -0,0 +1,31 @@
+import { Routes } from '@angular/router';
+import { SplitViewPrimaryComponent } from './split-view-primary.component';
+import { SplitViewSecondaryComponent } from './split-view-secondary.component';
+import { SplitViewSupplementaryComponent } from './split-view-supplementary.component';
+import { SplitViewInspectorComponent } from './split-view-inspector.component';
+
+// Since SplitViewDemoComponent is bootstrapped directly, we don't include it in routes.
+// The named outlets are defined in SplitViewDemoComponent's template,
+// and these child routes activate into those outlets.
+export const SPLIT_VIEW_ROUTES: Routes = [
+ {
+ path: 'primary',
+ component: SplitViewPrimaryComponent,
+ outlet: 'primary',
+ },
+ {
+ path: 'secondary',
+ component: SplitViewSecondaryComponent,
+ outlet: 'secondary',
+ },
+ {
+ path: 'supplementary',
+ component: SplitViewSupplementaryComponent,
+ outlet: 'supplementary',
+ },
+ {
+ path: 'inspector',
+ component: SplitViewInspectorComponent,
+ outlet: 'inspector',
+ },
+];
diff --git a/apps/nativescript-demo-ng/src/app/split-view-demo/split-view.state.ts b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view.state.ts
new file mode 100644
index 0000000..3b9cfa8
--- /dev/null
+++ b/apps/nativescript-demo-ng/src/app/split-view-demo/split-view.state.ts
@@ -0,0 +1,21 @@
+import { Injectable, signal } from '@angular/core';
+import { SplitView } from '@nativescript/core';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class SplitViewState {
+ inspectorVisible = signal(true);
+
+ onInspectorChange(event: any) {
+ console.log(`[SplitViewState] Inspector visibility changed: ${event.data.showing}`);
+ if (!event.data.showing) {
+ this.inspectorVisible.set(event.data.showing);
+ }
+ }
+
+ setInspectorVisible(visible: boolean) {
+ this.inspectorVisible.set(visible);
+ SplitView.getInstance().showInspector();
+ }
+}
diff --git a/apps/nativescript-demo-ng/src/main.ts b/apps/nativescript-demo-ng/src/main.ts
index e725d50..8083544 100644
--- a/apps/nativescript-demo-ng/src/main.ts
+++ b/apps/nativescript-demo-ng/src/main.ts
@@ -5,28 +5,33 @@ import {
provideNativeScriptRouter,
runNativeScriptAngularApp,
} from '@nativescript/angular';
-import { Trace, Utils } from '@nativescript/core';
+import { Trace, Utils, SplitView } from '@nativescript/core';
// import { AppModule } from './app/app.module';
import { withInterceptorsFromDi } from '@angular/common/http';
-import { AppComponent } from './app/app.component';
-import { routes } from './app/app.routes';
+// import { AppComponent } from './app/app.component';
+// import { routes } from './app/app.routes';
import { provideZonelessChangeDetection } from '@angular/core';
+import { SPLIT_VIEW_ROUTES } from './app/split-view-demo/split-view.routes';
+import { SplitViewDemoComponent } from './app/split-view-demo/split-view-demo.component';
const ZONELESS = true;
Trace.enable();
Trace.setCategories('ns-route-reuse-strategy,ns-router');
+// Set the split style before bootstrapping - 'triple' is needed for primary/supplementary/secondary layout
+SplitView.SplitStyle = 'triple';
+
runNativeScriptAngularApp({
appModuleBootstrap: () => {
if (__APPLE__) {
Utils.ios.setWindowBackgroundColor('#a6120d');
}
- return bootstrapApplication(AppComponent, {
+ return bootstrapApplication(SplitViewDemoComponent, {
providers: [
provideNativeScriptHttpClient(withInterceptorsFromDi()),
- provideNativeScriptRouter(routes),
+ provideNativeScriptRouter(SPLIT_VIEW_ROUTES),
ZONELESS ? provideZonelessChangeDetection() : provideNativeScriptNgZone(),
],
});
diff --git a/packages/angular/src/lib/element-registry/common-views.ts b/packages/angular/src/lib/element-registry/common-views.ts
index 3d8283c..f4436ec 100644
--- a/packages/angular/src/lib/element-registry/common-views.ts
+++ b/packages/angular/src/lib/element-registry/common-views.ts
@@ -1,4 +1,4 @@
-import { AbsoluteLayout, ActivityIndicator, Button, ContentView, DatePicker, DockLayout, FlexboxLayout, FormattedString, Frame, GridLayout, HtmlView, Image, Label, ListPicker, ListView, Page, Placeholder, Progress, ProxyViewContainer, Repeater, RootLayout, ScrollView, SearchBar, SegmentedBar, SegmentedBarItem, Slider, Span, StackLayout, Switch, TabView, TextField, TextView, TimePicker, WebView, WrapLayout } from '@nativescript/core';
+import { AbsoluteLayout, ActivityIndicator, Button, ContentView, DatePicker, DockLayout, FlexboxLayout, FormattedString, Frame, GridLayout, HtmlView, Image, Label, ListPicker, ListView, Page, Placeholder, Progress, ProxyViewContainer, Repeater, RootLayout, ScrollView, SearchBar, SegmentedBar, SegmentedBarItem, Slider, Span, SplitView, StackLayout, Switch, TabView, TextField, TextView, TimePicker, WebView, WrapLayout } from '@nativescript/core';
import { formattedStringMeta, frameMeta, textBaseMeta } from './metas';
import { registerElement } from './registry';
@@ -33,6 +33,7 @@ export function registerNativeScriptViewComponents() {
registerElement('SegmentedBar', () => SegmentedBar);
registerElement('SegmentedBarItem', () => SegmentedBarItem);
registerElement('Slider', () => Slider);
+ registerElement('SplitView', () => SplitView);
registerElement('StackLayout', () => StackLayout);
registerElement('FlexboxLayout', () => FlexboxLayout);
registerElement('Switch', () => Switch);