I have my App working in the browser (ionic serve):
singleton provider sets showLogin to false
upon login this value is updated
menu shows/hides items based on showLogin value
but when I upload it and test on IOS or Android the menu is not updated upon login (only when I close the App and reopen it). I am not sure why.
App.html:
<ion-menu [content]="mainContent">
<ion-header>
<ion-toolbar>
<ion-title>
Menu
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content id="side-menu21">
<ion-list id="menu-list1">
<ion-item color="none" menuClose="" on-click="goToDriveBidder()" id="menu-list-item1">
Home
</ion-item>
<ion-item color="none" menuClose="" on-click="goToHuidigeRit()" id="menu-list-item2" [hidden]="!singleton.showLogin">
Huidige rit
</ion-item>
<ion-item color="none" menuClose="" on-click="goToMijnRitten()" id="menu-list-item3" [hidden]="!singleton.showLogin">
Mijn ritten
</ion-item>
<ion-item color="none" menuClose="" on-click="goToLogout()" id="menu-list-item3" [hidden]="!singleton.showLogin">
Logout
</ion-item>
<ion-item color="none" menuClose="" on-click="goToLogin()" id="menu-list-item3" [hidden]="singleton.showLogin">
Login
</ion-item>
<ion-item color="none" menuClose="" on-click="goToHelp()" id="menu-list-item4">
Help
</ion-item>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav #mainContent [root]="rootPage" swipeBackEnabled="false"></ion-nav>
singleton.ts:
import { Injectable } from '#angular/core';
#Injectable()
export class SingletonService {
public showLogin:boolean = false;
}
and login.ts updates showLogin when login is succesful:
this.singleton.showLogin = true;
and it redirects to the homepage:
location.reload(true);
In the browser the correct menu items show now, but not in ionic view....what I am doing wrong?
Related
In a fresh laravel installation i'm trying to make layout persistent following the inertia doc https://inertiajs.com/pages
app.js
require('./bootstrap');
// Import modules...
import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '#inertiajs/inertia-vue3';
import { InertiaProgress } from '#inertiajs/progress';
import AppLayout from '#/Layouts/AppLayout';
const el = document.getElementById('app');
createApp({
render: () =>
h(InertiaApp, {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: name => import(`./Pages/${name}`)
.then(({ default: page }) => {
if (page.layout === undefined) {
page.layout = AppLayout
}
return page
}),
}),
})
.mixin({ methods: { route } })
.use(InertiaPlugin)
.mount(el);
InertiaProgress.init({ color: '#4B5563' });
Dashboard.vue (here i replace the default app-layout wrapper by div)
<template>
<div>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Dashboard
</h2>
</template>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
<welcome />
</div>
</div>
</div>
</div>
</template>
<script>
import Welcome from '#/Jetstream/Welcome'
export default {
components: {
Welcome,
},
}
</script>
While compiling i get this error :
Error: Codegen node is missing for element/if/for node. Apply
appropriate transforms first.
I can't figure out what that means. Is there a reason why the default laravel app with jetstream and inertia doesn't use persistent layout?
If the header slot is in AppLayout aka the persistent one, you cannot use this way (because there is no slot yet? I don't know but I know persistent layouts do mount after child components, this can be the culprit). As a solution, create another layout, ie PageLayout, with named slots and use that layout to build your dashboard and other pages:
AppLayout.vue
<template>
<div>Persistent stuff...</div>
<slot />
<div>Persistent stuff...</div>
</template>
PageLayout.vue
<template>
<slot name="header" />
<slot name="content" />
<div>PageLayout stuff...</div>
</template>
Dashboard.vue
<template>
<PageLayout>
<template #header>
<h1>Dashboard</h1>
</template>
<template #content>
<p>Welcome user!</p>
</template>
</PageLayout>
</template>
<script>
import AppLayout from 'AppLayout'
import PageLayout from 'PageLayout'
export default {
layout: AppLayout, // Persistent layout
components: {
PageLayout // Regular layout
}
</script>
There is an ongoing discussion here:
https://github.com/inertiajs/inertia/issues/171
You need the app-layout as you need to extend from it <template #header>
I have a dropdown in SPFX webpart in sharepoint online. In that dropdown, onchange, I am constructing a url with # tag.
E.x. https://sharepointonine/default.aspx#2349-234234-23434
I need to navigate to this new url. I am not sure how to accomplish things.
I have tried:
window.location = url //Gives error that string is not assignable to Location
window.location.href= url//does not reload the page
window.open(url, "_self")//does not reload the page
window.location.assign(url);//does not reload the page
window.location.replace(url);//does not reload the page
Any help?
You can create element 'a' and call click to open url
let a = document.createElement('a');
a.href = 'your link to open';
a.click();
this works fine.
Also you can use react-router, as describe here
There are also redirect link:
import { Redirect } from 'react-router';
When you need to redirect to som url, you render redirect:
<Redirect to={'/to url'}></Redirect>
I test with no framework SPFX.
Test result:
Test code for your reference:
public render(): void {
this.domElement.innerHTML = `
<div class="${styles.noframeworkSpfx}">
<div class="${styles.container}">
<div class="${styles.row}">
<div class="${styles.column}">
<span class="${styles.title}">Welcome to SharePoint!</span>
<p class="${styles.subTitle}">Customize SharePoint experiences using Web Parts.</p>
<p class="${styles.description}">${escape(this.properties.description)}</p>
<a href="https://aka.ms/spfx" class="${styles.button}">
<span class="${styles.label}">Learn more</span>
</a>
<select id="option" >
<option value="test1">test1</option>
<option value="test2">test2</option>
<option value="test3">test3</option>
</select>
</div>
</div>
</div>
</div>`;
this.domElement.querySelector('#option').addEventListener('change', (e) => {
window.location.href="https://www.google.com/search?q="+e.target["value"]
})
}
I have an Ionic3 application with side-menu. I need to create a menu with sub-menu, but in this sub-menu I have another level of list(sub-menu into sub-menu).
I have this kind of example but only with one level of sub menu :
https://stackblitz.com/edit/multi-level-side-menu?file=app%2Fapp.component.ts
app.html
<ion-menu [content]="content">
<ion-header>
<ion-toolbar class="menu-header">
<ion-title>Menu</ion-title>
</ion-toolbar></ion-header>
<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>
app.component.ts
import { Component, ViewChild } from '#angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { HomePage } from '../pages/home/home';
import { ListPage } from '../pages/list/list';
import { TermsPage } from '../pages/terms/terms';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
#ViewChild(Nav) nav: Nav;
rootPage: any = HomePage;
pages: Array<{title: string, component: any}>;
constructor(public platform: Platform, public statusBar: StatusBar, public
splashScreen: SplashScreen) {
this.initializeApp();
// used for an example of ngFor and navigation
this.pages = [
{ title: 'Home', component: HomePage },
{ title: 'List', component: ListPage }
];
}
initializeApp() {
this.platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
openPage(page) {
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.nav.setRoot(page.component);
}
}
Your array should be of multiple level of array i.e array with in array (depends on how much sub-level of menu you want) and then display your array content by using nesting list (list with in list)
for example :
your array be like :
public appPages = [
{
list_header: 'Client List',
icon: 'home',
subList: [{
subList_title: [
{
title: 'a'
},
{
title: 'b'
}
]
}]
}]
and your list in your HTML like :
<ion-list>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages" text-wrap>
<ion-item [routerDirection]="'root'" [routerLink]="[p.url]">
<ion-icon slot="start" [name]="p.icon"></ion-icon>
<ion-label>
{{p.list_header}}
</ion-label>
<ion-list>
<ion-item *ngFor="let sub of p.subList" text-wrap>
<ion-list>
<ion-item lines="none" *ngFor="let t of sub.subList_title" text-wrap>
{{t.title}}
</ion-item>
</ion-list>
</ion-item>
</ion-list>
</ion-item>
</ion-menu-toggle>
</ion-list>
#Vitali
you can also use <ion-item-group> tag to group your subList within <ion-list> so this will avoid use of nested <ion-list> .
<ion-list id="sidenav" *ngFor="let p of appPages;index as i">
<ion-item lines="full" (click)="toggleLevel1('idx'+i)" [ngClass]="{active: isLevel1Shown('idx'+i)}"
lines="full">
<ion-icon slot="start" [name]="p.icon"></ion-icon>
{{p.list_header}}
<ion-icon color="dark" slot="end" *ngIf="p.subList_title != null" [name]="isLevel1Shown('idx'+i) ? 'arrow-dropdown' : 'arrow-dropright'">
</ion-icon>
</ion-item>
<ion-item-group *ngFor="let sub of p.subList_title" submenu [class.visible]="isLevel1Shown('idx'+i)">
<ion-item submenu-item *ngIf="isLevel1Shown('idx'+i)" lines="none">{{sub.title}}</ion-item>
</ion-item-group>
</ion-list>
I try to make the menu button not to show when the back button is showing. is there a way to let Ionic take care of that? or it's up to me?
for example if i use ui-sref to go from app.users to app.users.add or app.users.details i expect the menu button to be hidden and the back button to show, but they're both showing when i go to nested views. example:
<button class="button button-positive" ui-sref="app.users.details({id:user.id})"> User details </button>
app.js
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html'
//controller: 'AppCtrl'
})
.state('app.users', {
url: '/users',
views: {
'menuContent#app' : {
controller: 'UsersCtrl',
templateUrl: 'templates/users.html'
}
}
})
.state('app.users.add', {
url: '/addUsers',
views: {
'menuContent#app' : {
controller: 'AddUserCtrl',
templateUrl: 'templates/add_user.html'
}
}
})
.state('app.users.details', {
url: '/userDetails/:id',
views: {
'menuContent#app' : {
controller: 'UserDetailsCtrl',
templateUrl: 'templates/details_user.html'
}
}
})
}
menu.html
<ion-side-menus>
<ion-pane ion-side-menu-content>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button class="button-clear">
<i class="icon ion-ios7-arrow-forward"></i> back
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view name="menuContent" animation="slide-right-left"></ion-nav-view>
</ion-pane>
<ion-side-menu side="right">
<header class="bar bar-header bar-stable">
<h1 class="title">Title</h1>
</header>
<ion-content class="has-header">
<ion-list>
<ion-item nav-clear menu-close ui-sref="app.users">
Users
</ion-item>
<ion-item nav-clear menu-close ui-sref="app.users.add">
New user
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
My views structure is as such:
<ion-view title="Title">
<ion-nav-buttons side="right">
<button menu-toggle="right"class="button button-icon icon ion-navicon"></button>
</ion-nav-buttons>
<ion-content class="has-header">
...
View Content
...
</ion-content>
</ion-view>
This is done by ionic by default now in beta 14. You can also toggle this by this attribute.
<ion-side-menus enable-menu-with-back-views="false">
Relative Codepen
Sidemenu Starter Project
Sidemenu Docs
Is also possible to override that from a child page just adding the ion-side-menus directive inside the child template:
<ion-side-menus enable-menu-with-back-views="true"></ion-side-menus>
<ion-view view-title="My Child page">
<ion-content>
<h1>HEY</h1>
</ion-content>
</ion-view>
This will add the complete navigation bar (ion-nav-bar) inside your child page that was added into menu.html template (according with the example above)
Place the navbar with menu button on the html page on which you need menu button and place navbar with back button on the page where you need back button.
Like this I need Menu On home page so place your navbar on homepage with menu button
<ion-view title="home">
<ion-nav-bar class="bar-stable main-header-nav home-page">
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu- toggle="left"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-content></ion-content>
</ion-view>
And I need back button on Inbox page so use navbar with backbutton on inbox page
<ion-view title="">
<ion-nav-bar class="bar-stable main-header-nav home-page">
<ion-nav-back-button class="button-clear go-back">
</ion-nav-back-button>
</ion-nav-bar>
<ion-content></ion-content>
</ion-view>
I solved in 2019 adding the property "menuToggle" to the Button. That tells Ionic/Angular that the function of that button is to be the "Hamburguer Button" so, Angular understand and hide it when the "Back Arrow Button" is shown.
<button menuToggle ion-button icon-only (click)="btnHamburger()">
<ion-icon name="menu"></ion-icon>
</button>
Everything works perfectly. The appbar is displayed only in the home, but if I exit the App without closing and again opening it, it disappears the appbar
In home.js
WinJS.UI.Pages.define("/pages/home.html", {
ready: function (element, options) {
appBar = document.getElementById("createAppBar").winControl;
appBar.getCommandById("cmdSettings").addEventListener("click", doClickSettings, false);
appBar.getCommandById("cmdCalibrate").addEventListener("click", doClickCalibrate, false);
appBar.getCommandById("cmdShare").addEventListener("click", doClickShare, false);
appBar.getCommandById("cmdEdit").addEventListener("click", doClickCamera, false);
getLoc();
}});
...
In home.html
<div id="createAppBar" data-win-control="WinJS.UI.AppBar" data-win-options="{closedDisplayMode:'minimal'}">
<button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdSettings',label:'Ajustes',icon:'settings',tooltip:'Ajustes'}"></button>
<button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdCalibrate',label:'Calibrar',icon:'fourbars',tooltip:'Calibrar'}"></button>
<button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdShare',label:'Compartir',icon:'like',tooltip:'Corre la voz'}"></button>
<button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdEdit',label:'about',icon:'like',tooltip:'Corre la voz'}"></button>
<!--<button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdCamera',label:'Camera',icon:'camera',section:'selection',tooltip:'Take a picture'}"></button>-->
Can someone help me?
Tnx in adv!
Looks like it is a bug in WinJS.
https://github.com/winjs/winjs/issues/140