Show multiple pages for large screen sizes in Ionic 3 - ionic-framework

I'm building a simple app with a side menu and two ion-tab. What I am trying to do is, when the screen wide enough, forget about the tabs and open both pages side by side:
To keep the menu visible if the screen is large enough, I am using:
<ion-split-pane when="lg">
And to hide the Tabs:
TS file: this.showTabs = platform.width() < 992;
And then, in the HTML file, I just add the attribute: *ngIf="showTabs"
Is it possible to load two pages inside an ion-content? Any alternative solution?
Any help would be appreciated!

Ok, I've found a solution for this. I'll post it here in case someone experiences the same problem.
We can create a custom component with:
ionic generate component name-of-component
The components can be embedded within the ionic pages. To use them in a Page, you just have to import the component in the .module.ts of the Page and then use the HTML tag with the selector name of the component, as Ivaro18 mentioned:
<component-name></component-name>
If you want to use lazy loading, you can create a components.module.ts inside the components folder to act as an index of all the custom components. It would look like this:
import { NgModule } from '#angular/core';
import { IonicModule } from 'ionic-angular';
import { Component1 } from './component1/component1';
import { Component2 } from './component2/component2';
import { Component3 } from './component3/component3';
#NgModule({
declarations: [
Component1,
Component2,
Component3
],
imports: [IonicModule],
exports: [
Component1,
Component2,
Component3
]
})
export class ComponentsModule{}
Then, in the Pages, we would import ComponentsModule. That would allow us to lazy load any of the components:
<component-2-selector></component-2-selector>
Hope this helps!

Related

Embedding a tableau dashboard into react messes up the formatting of the dashboard

I have a tableau dashboard that I am trying to embed into a react website using the tableau-api npm package. Although it looks fine on tableau public, the layout changes when I embed it. How do I ensure that the layout stays the same when I embed it in react?
Edit: here is my code. I used this answer as reference
import React, { Component } from 'react';
import tableau from 'tableau-api';
class Visualization extends Component {
componentDidMount() {
this.initTableau()
}
initTableau() {
const vizUrl = 'url';
const vizContainer = this.vizContainer;
let viz = new window.tableau.Viz(vizContainer, vizUrl)
}
render() {
return (
<div ref={(div) => { this.vizContainer = div }}>
</div>
)
}
}
export default Visualization;
There are a couple of options you should take a look at
Change the size of your dashboard from automatic to fixed (reference here). This will help if you have floating elements in your dashboard
Add your preferred device to the dashboard panel
Change the fit option to entire view
If none of these options work, I would recommend you share a photo of your dashboard and your code to be able to debug

How to hide header on scroll in ionic 4?

I wanted to know how I can hide a header in Ionic 4 by scrolling down the page, and re-show it when scrolling up.
I found many solutions on how to do that, but they all turned out to not working or being out-of-date.
So I collected all piece of information I could find to provide this answer.
Thanks to this video I got it to work.
First of all call ionic g directive directives/hide-header. You can of course replace directive/hide-header with your own path and name.
hide-header.directive.ts
import { Directive, HostListener, Input, OnInit, Renderer2 } from '#angular/core';
import { DomController } from '#ionic/angular';
#Directive({
selector: '[appHideHeader]'
})
export class HideHeaderDirective implements OnInit {
#Input('header') header: any;
private lastY = 0;
constructor(
private renderer: Renderer2,
private domCtrl: DomController
) { }
ngOnInit(): void {
this.header = this.header.el;
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'transition', 'margin-top 700ms');
});
}
#HostListener('ionScroll', ['$event']) onContentScroll($event: any) {
if ($event.detail.scrollTop > this.lastY) {
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'margin-top', `-${ this.header.clientHeight }px`);
});
} else {
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'margin-top', '0');
});
}
this.lastY = $event.detail.scrollTop;
}
}
After that, in your template:
<ion-header #header>
<ion-toolbar><ion-title>Test</ion-title></ion-toolbar>
</ion-header>
<ion-content scrollEvents="true" appHideHeader [header]="header">
</ion-content>
Take care of the scrollEvents, appHideHeader and the [header] attributes! The last one takes the header element as argument, in this case #header.
Most of the code is the same as shown in the video. I changed the host-property from the #Directive and used the more up-to-date HostListener.
If you want to use the directive in more than one directive, you need to create a SharedModule.
To do so, create the module with ng g module shared. After that, add the HideHeaderDirective to the declarations and the exports array.
shared.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HideHeaderDirective } from './directives/hide-header.directive';
#NgModule({
declarations: [HideHeaderDirective],
exports: [HideHeaderDirective],
imports: [
CommonModule
]
})
export class SharedModule {}
Now add the shared module to all the modules you want to use the directive in.
Note: You cannot import the directive in app.module.ts and use it in a submodule! You have to import the shared module in every direct module you want to use the directive in.
My current versions of node, npm and ionic:
For this you can just place the ion-header before the ion-content. this is the simple answer for that.

Dynamically rendering react components

I'm new to reactjs and I'm having a hell of a time understanding this bug.
I've read this, and it seems like the solution is there but I'm drawing a blank on how to implement this correctly:
https://facebook.github.io/react/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized
I am trying to render components based on classNames of clicked elements. The classNames match to component names. When I click an element it calls a function that sets the state of my app to that elements className. I then render the component based on the new state.
When testing, if I place the component directly into my app (not rendering the component name dynamically), it works just fine. But when i render the component name dynamically react thinks it's a built-in DOM element and doesn't render properly at all.
In this image you can see both components, rendered next to each other:
both components, first directly added, and the second with the name rendered dynamically
here is my app component code that is rendering everything:
import React, { Component } from 'react';
import logo from '../logo.svg';
import '../css/App.css';
import menus from '../menus';
import MainNav from './MainNav';
import Products from './Products';
import Demos from './Demos';
import Industry from './Industry';
import Customers from './Customers';
import Trials from './Trials';
import Contact from './Contact';
import Newsroom from './Newsroom';
import About from './About';
import Home from './Home';
class App extends Component {
constructor() {
super();
this.chooseComponent = this.chooseComponent.bind(this);
this.state = {
allMenus: menus,
componentMenu: menus,
//sets initial component to load, changes on each click to the clicked component
clickedComponent: Home
};
}
chooseComponent(event) {
//save the classname of the menu i click
var clickedComp = event.target.className;
//saves a reference to a json object for later use
var menu = menus[clickedComp];
//adds those two vars to the state
this.setState({
componentMenu: menu,
clickedComponent: clickedComp
});
}
render() {
//saves a var for rendering the currently clicked component
var ActiveComponent = this.state.clickedComponent;
return (
<div className="App">
<MainNav choose={this.chooseComponent}/>
//renders the components directly without issue
<Products menuData={this.state.componentMenu} />
//renders the component dynamically with problems
<ActiveComponent menuData={this.state.componentMenu} />
</div>
);
}
}
export default App;
here is and example of one of my component being rendered in the App that's giving problems:
import React from 'react';
import products from '../products';
import ProductsMenu from './ProductsMenu';
import Platform from './Platform';
import Applications from './Applications';
import ExMachina from './ExMachina';
import ProductsHome from './ProductsHome';
import Submenu from './Submenu';
import menus from '../menus';
class Products extends React.Component {
constructor() {
super();
this.showContent=this.showContent.bind(this);
this.state = {
productsOverview: products,
content: <ProductsHome />
}
}
render(props) {
return (
<div className="content">
{this.state.content}
</div>
);
}
}
export default Products;

Ionic SqlStorage is not defined

I'm trying to use SqlStorage in an ionic app. I'm getting the error in the title. I'm guessing I need to include SqlStorage but I'm not sure where. My code looks a lot like what's in the docs http://ionicframework.com/docs/v2/api/platform/storage/SqlStorage/ . How do you include SqlStorage?
var prefrences = {
foo: bar
}
let storage = new Storage(SqlStorage);
storage.set('storedPreferences', preferences);
Add SqlStorage to your list of 'include' packages via import statement. i.e
import {SqlStorage} from 'ionic-angular';
For example
import {SqlStorage,...} from 'ionic-angular';
#Page({
templateUrl: 'path/to/template'
})
export class MyPage {
constructor(){
let storage = new Storage(SqlStorage);
...
}
...
}

How to redirect to an external URL in Angular2?

What is the method for redirecting the user to a completely external URL in Angular 2. For example, if I need to redirect the user to an OAuth2 server in order to authenticate, how would I do that?
Location.go(), Router.navigate(), and Router.navigateByUrl() are fine for sending the user to another section (route) within the Angular 2 app, but I can't see how they could be used to redirect to an external site?
You can use this-> window.location.href = '...';
This would change the page to whatever you want..
An Angular approach to the methods previously described is to import DOCUMENT from #angular/common (or #angular/platform-browser in Angular
< 4) and use
document.location.href = 'https://stackoverflow.com';
inside a function.
some-page.component.ts
import { DOCUMENT } from '#angular/common';
...
constructor(#Inject(DOCUMENT) private document: Document) { }
goToUrl(): void {
this.document.location.href = 'https://stackoverflow.com';
}
some-page.component.html
<button type="button" (click)="goToUrl()">Click me!</button>
Check out the platformBrowser repo for more info.
The solution, as Dennis Smolek said, is dead simple. Set window.location.href to the URL you want to switch to and it just works.
For example, if you had this method in your component's class file (controller):
goCNN() {
window.location.href='http://www.cnn.com/';
}
Then you could call it quite simply with the appropriate (click) call on a button (or whatever) in your template:
<button (click)="goCNN()">Go to CNN</button>
I think you need à target="_blank", so then you can use window.open :
gotoGoogle() : void {
window.open("https://www.google.com", "_blank");
}
If you've been using the OnDestry lifecycle hook, you might be interested in using something like this before calling window.location.href=...
this.router.ngOnDestroy();
window.location.href = 'http://www.cnn.com/';
that will trigger the OnDestry callback in your component that you might like.
Ohh, and also:
import { Router } from '#angular/router';
is where you find the router.
---EDIT---
Sadly, I might have been wrong in the example above. At least it's not working as exepected in my production code right now - so, until I have time to investigate further, I solve it like this (since my app really need the hook when possible)
this.router.navigate(["/"]).then(result=>{window.location.href = 'http://www.cnn.com/';});
Basically routing to any (dummy) route to force the hook, and then navigate as requested.
in newer versions of Angular with window as an any
(window as any).open(someUrl, "_blank");
There are 2 options:
if you want to redirect in same window/tab
gotoExternalDomain(){
window.location.href='http://google.com/'
}
if you want to redirect in new tab
gotoExternalDomain(){
(window as any).open("http://google.com/", "_blank");
}
After ripping my head off, the solution is just to add http:// to href.
Go somewhere
I used window.location.href='http://external-url';
For me the the redirects worked in Chrome, but didn't work in Firefox.
The following code resolved my problem:
window.location.assign('http://external-url');
I did it using Angular 2 Location since I didn't want to manipulate the global window object myself.
https://angular.io/docs/ts/latest/api/common/index/Location-class.html#!#prepareExternalUrl-anchor
It can be done like this:
import {Component} from '#angular/core';
import {Location} from '#angular/common';
#Component({selector: 'app-component'})
class AppCmp {
constructor(location: Location) {
location.go('/foo');
}
}
You can redirect with multiple ways:
like
window.location.href = 'redirect_url';
another way Angular document:
import document from angular and the document must be inject as well as bellow otherwise you will get error
import { DOCUMENT } from '#angular/common';
export class AppComponent {
constructor(
#Inject(DOCUMENT) private document: Document
) {}
this.document.location.href = 'redirect_url';
}
None of the above solutions worked for me, I just added
window.location.href = "www.google.com"
event.preventDefault();
This worked for me.
Or try using
window.location.replace("www.google.com");
To use #Inject, you must import it. I didn't see this in any of the answers.
TS file:
import { Component, Inject } from '#angular/core';
import { DOCUMENT } from '#angular/common';
#Component({
selector: 'app-my-comp.page',
templateUrl: './my-comp.page.component.html',
styleUrls: ['./my-comp.page.component.scss']
})
export class MyCompPageComponent {
constructor(
#Inject(DOCUMENT) private document: Document
) { }
goToUrl(): void {
this.document.location.href = 'https://google.com/';
}
}
HTML file:
<button type="button" (click)="goToUrl()">Google</button>
In your component.ts
import { Component } from '#angular/core';
#Component({
...
})
export class AppComponent {
...
goToSpecificUrl(url): void {
window.location.href=url;
}
gotoGoogle() : void {
window.location.href='https://www.google.com';
}
}
In your component.html
<button type="button" (click)="goToSpecificUrl('http://stackoverflow.com/')">Open URL</button>
<button type="button" (click)="gotoGoogle()">Open Google</button>
<li *ngFor="item of itemList" (click)="goToSpecificUrl(item.link)"> // (click) don't enable pointer when we hover so we should enable it by using css like: **cursor: pointer;**
Just simple as this
window.location.href='http://www.google.com/';