I am trying to write a modal with a form in Ionic. For some reason, any time I associate an ngModel with <ion-checkbox> (or <ion-radio> for that matter), my modal does not show up (the constructor is called).
My controller:
import { Component } from '#angular/core';
import { NavController, NavParams, ViewController } from 'ionic-angular';
#Component({
selector: 'page-alert-modal',
templateUrl: 'alert-modal.html',
})
export class AlertModalPage {
formData = {};
constructor(public navCtrl: NavController, public navParams: NavParams, viewCtrl:ViewController) {
//this.formData = {xy:"", name:"", obd:""};
console.log ("*** Modal constructor");
}
logForm() {
console.log ("Submitted")
}
My template:
<ion-content padding>
<form (ngSubmit)="logForm()">
<ion-list-header>Trip Details</ion-list-header>
<ion-item>
<ion-label floating>Name your trip:</ion-label>
<ion-input [(ngModel)]="formData.name" name="tripname"></ion-input>
</ion-item>
<ion-item>
<ion-label>Track GPS lat/long</ion-label>
<!-- if I enable the line below, the modal does not show up -->
<!--<ion-checkbox [(ngModel)]="formData.xy"></ion-checkbox>-->
<ion-checkbox></ion-checkbox>
</ion-item>
<ion-item>
<ion-label>Read BLE OBD</ion-label>
<!-- if I enable the line below, the modal does not show up -->
<!--<ion-checkbox [(ngModel)]="formData.obd"></ion-checkbox>-->
<ion-checkbox></ion-checkbox>
</ion-item>
</form>
<button ion-button block outline>Ok</button>
</ion-content>
My ionic info:
cli packages:
#ionic/cli-plugin-cordova : 1.5.0
#ionic/cli-plugin-ionic-angular : 1.4.0
#ionic/cli-utils : 1.6.0
ionic (Ionic CLI) : 3.6.0
global packages:
Cordova CLI : 7.0.1
local packages:
#ionic/app-scripts : 2.0.2
Cordova Platforms : android 6.2.3 ios 4.4.0
Ionic Framework : ionic-angular 3.5.3
System:
Android SDK Tools : 25.2.5
Node : v8.1.4
OS : macOS Sierra
Xcode : Xcode 8.3.3 Build version 8E3004b
ios-deploy : 1.9.0
ios-sim : 5.0.2
npm : 5.0.3
Problem solved. I missed this part in the docs
Note: If you use ngModel within a Form tag, you have to provide a name
property. If you do not, you must set standalone to true in
ngModelOptions
So this worked:
<ion-item>
<ion-label>Track GPS lat/long</ion-label>
<ion-checkbox [(ngModel)]="formData.xy" name="xy"></ion-checkbox>
</ion-item>
Related
The Foundation 6 Responsive menu shows the mobile version on initial page load / refresh and is not "responsive". When Turbolinks loads the page, The proper menu appears and it is "responsive". "responsive" meaning the Javascript to change between the menus.
This is super weird because the usual Turbolinks problem is the opposite, where it works on the initial page load but not on subsequent ones. All other Foundation 6 related Javascript, like modals, work as expected no matter how the page is loaded.
I have just moved to an updated version of rails 5.2. I was on 5.2.1, webpacker 3.5, and foundation 6.5.0-rc.4. Everything worked as expected. Turbolinks has not changed versions.
I am now using Foundation 6.5.3, Rails 5.2.3, Webpack 4.34.0, Stimulus 1.1.1 ,and Turbolinks 5.2.0. No additional Gems except necessary Rails and dependencies are used. I have tried Foundation 6.5.3, 6.5.2, 6.5.1, 6.5.0, 6.5.0-rc.4, 6.4.3. None seem to revert back to normal behavior.
I have tried to reorder my Webpack application.js pack file to load modules and initialize foundation. I have tried initializing Foundation in a stimulus controller's initialize function. I have tried attaching the listener with and without Jquery. I refuse to try an inline script at the end of the html and allow unsafe-inline in my CSP. I have tried CSS solutions, no effect. I have tried messing with data-show-for attributes as well as html visibility classes but that didn't help either. I have tried adding and removing parent elements, no change. There are no errors in the browser console. Adding "ready" to the listener for "turbolinks:load" does nothing. I have looked for other Turbolinks listeners to try, but found none that made sense. I have tried to initialize it outside of and in addition to the turbolinks:load listener and it still fails, however errors show up this time in the console show foundation is initializing twice. (Tried to initialize responsive-toggle on an element that already has a Foundation plugin.)
I have included all the pertinent files to recreate this issue, unfortunately I don't have a live site to put up at the moment.
rails new foundationtestsite -T -d postgresql -S --webpack=stimulus --skip-listen
package.json (fluff removed)
{
...,
"dependencies": {
"#rails/webpacker": "^4.0.7",
"actioncable": "^5.2.3",
"activestorage": "^5.2.3",
"foundation-sites": "^6.5.3",
"jquery": "^3.4.1",
"rails-ujs": "^5.2.3",
"stimulus": "^1.1.1",
"turbolinks": "^5.2.0",
"webpack": "^4.34.0",
"what-input": "^5.2.3"
},
...
}
application.js (webpack entry / pack file)
import $ from 'jquery'
import jQuery from 'jquery'
import Rails from 'rails-ujs';
import Turbolinks from 'turbolinks';
import cable from 'actioncable';
// import "controllers"
import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"
const application = Application.start()
const context = require.context("controllers", true, /.js$/)
// Turbolinks
application.load(definitionsFromContext(context))
Turbolinks.start()
// images
const images = require.context('../images', true)
const imagePath = (name) => images(name, true)
// style sheets
import '../stylesheets/application.scss';
// foundation sites 6
import foundation from 'foundation-sites';
import '../javascripts/foundation_startup.js';
foundation_startup.js
import $ from 'jquery'
import jQuery from 'jquery'
import 'rails-ujs'
import 'foundation-sites'
$(document).on('turbolinks:load', function(){
$(function(){ $(document).foundation() })
});
html from menu partial (rendered as first element of body)
<div data-controller="menu" data-target="menu.menu" class="cell shrink header medium-cell-block-container">
<div class="title-bar" data-responsive-toggle="example-animated-menu" data-hide-for="medium" data-target="menu.titleBar">
<button class="menu-icon" type="button" data-toggle="example-animated-menu"></button>
<div class="title-bar-title">Menu</div>
</div>
<div class="top-bar" id="example-animated-menu" data-target="menu.topBar">
<div class="top-bar-left">
<ul class="dropdown menu" data-dropdown-menu>
<li><%= link_to "Home", root_path%></li>
</ul>
</div>
</div>
</div>
I am trying to push new pages inside the current page's <div> element. I have tried various methods found on SO but nothing worked for me. I have this code right now which doesn't work.
<ion-content padding>
<div #pageView>
</div>
</ion-content>
import { Component, ViewChild } from '#angular/core';
import { IonicPage, NavController, NavParams, PopoverController } from 'ionic-angular';
export class Vehiclemaintenance {
#ViewChild('pageView') nav: NavController
Constructor(public navCtrl: NavController){}
loadPage(){
this.nav.push(myComponent)
}
}
This causes an error
ERROR TypeError: _this.nav.push is not a function
Where am I going wrong!
* Update that worked *
Instead of using a <div> element I used <ion-nav>
I created a page with 3 tabs using ionic 2.Inside one page I created one button and on click of that button I navigate to a new child page by executing
the push command but whenever I am clicking the tab containing the child page I am not able to see the root page instead I see the new child page.
I want to see the root page on revisit of the tab page.
Below is my code.. here you can check in about.html i have placed one button to navigate to a child page.Navigation is happening but once I navigate then I am not able to see the about tab page without clicking on back button
tabs.html
<ion-tabs>
<ion-tab [root]="tab1Root" tabTitle="Home" tabIcon="home"></ion-tab>
<ion-tab [root]="tab2Root" tabTitle="About" tabIcon="information-circle"></ion-tab>
<ion-tab [root]="tab3Root" tabTitle="Contact" tabIcon="contacts"></ion-tab>
</ion-tabs>
tabs.ts
import { Component } from '#angular/core';
import { HomePage } from '../home/home';
import { AboutPage } from '../about/about';
import { ContactPage } from '../contact/contact';
#Component({
templateUrl: 'tabs.html'
})
export class TabsPage {
// this tells the tabs component which Pages
// should be each tab's root Page
tab1Root: any = HomePage;
tab2Root: any = AboutPage;
tab3Root: any = ContactPage;
constructor() {
}
}
abuot.html
<ion-header>
<ion-navbar>
<ion-title>
About
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button ion-button (click)="navigate()" ion-button color="secondary">GO to LIst</button>
<!-- <button [navPush]="listPage" ion-button color="secondary">Go To About</button> -->
<!-- <button ion-button color="secondary">Secondary</button> -->
</ion-content>
about.ts
import { Component } from '#angular/core';
import {ListPage} from '../list/list';
import {ViewController, NavController} from 'ionic-angular';
#Component({
selector: 'page-about',
templateUrl: 'about.html'
})
export class AboutPage {
constructor(public navCtrl: NavController,public viewctr: ViewController) {
}
navigate(){
this.navCtrl.push(ListPage);
}
}
Just a stab in the dark since we cannot see any of your code (which should be an addition to any question on here). You could try using .setRoot() to get to the root page you're wanting.
import { NavController } from 'ionic-angular';
import { NameOfPage } from '../NameOfPage';
pageYouWant: any = NameOfPage;
constructor(public navctrl: NavController){}
onClickFunction(){
this.navCtrl.setRoot(pageYouWant)
}
ion-tabs and ion-content overlaps ion-header when i load an image in the header, it only happens the first time i'm visiting the page, after that it loads well.
this is the component
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'app/home.page.html'
})
export class HomePage {
public image: string;
appName = 'Ionic App';
constructor(public navController: NavController) { }
ionViewDidLoad(){
this.image = "https://source.unsplash.com/640x300/?technology"
}
}
Here is the html
<ion-header>
<ion-navbar>
<ion-title></ion-title>
</ion-navbar>
<img class="cabecera" [src]="image" width="100%">
</ion-header>
<ion-content padding class="contenido">
Welcome to this <ion-icon name="ionic"></ion-icon> <b>Ionic 2 app</b>.
</ion-content>
Its posible to view an example in this plunker
https://plnkr.co/edit/CpBXmn?p=preview
The problem is that you are only loading the image (in the ionViewDidLoad function) after the rest of the content is loaded. After loading the image you need to resize the content, as described in this issue.
Add ViewChild and Content to your imports from #angular/core and ionic-angular, respectively:
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
Use #ViewChild to select the class for the ion-content component:
// ...
export class HomePage {
#ViewChild(Content) content: Content;
// ...
Then, once the image is loaded, call the resize method on content:
this.content.resize();
I am presently using check boxes to track when tasks have been completed in my ionic 2 App. Is there a way save the date/time from the mobile device when this checkbox is selected.
<ion-list>
<ion-item>
<ion-label>Task 1</ion-label>
<ion-checkbox [(ngModel)]="data.task1"></ion-checkbox>
</ion-item>
</ion-list>
You could use the Date object from Javascript to do so, like you can see in this plunker.
Your Component:
import { Component } from "#angular/core";
#Component({
templateUrl:"home.html"
})
export class HomePage {
public data: any;
public dateTime : string = '';
constructor() {
this.data = {
task1 : false
}
}
public changeCheckBox() {
if(this.data.task1) {
this.dateTime = new Date();
}
}
}
Your view:
<ion-content>
<ion-list>
<ion-item>
<ion-label>Task 1</ion-label>
<ion-checkbox [(ngModel)]="data.task1" (ionChange)="changeCheckBox()"></ion-checkbox>
</ion-item>
<ion-item>
<ion-label>Timestamp: {{ dateTime }}</ion-label>
</ion-item>
</ion-list>
</ion-content>
Of course you can obtain detailed information by using some of the get methods:
Date.prototype.getDate()
Date.prototype.getDay()
Date.prototype.getFullYear()
Date.prototype.getHours()
Date.prototype.getMilliseconds()
Date.prototype.getMinutes()
Date.prototype.getMonth()
Date.prototype.getSeconds()
Date.prototype.getTime()
Date.prototype.getTimezoneOffset()
Date.prototype.getUTCDate()
Date.prototype.getUTCDay()
Date.prototype.getUTCFullYear()
Date.prototype.getUTCHours()
Date.prototype.getUTCMilliseconds()
Date.prototype.getUTCMinutes()
Date.prototype.getUTCMonth()
Date.prototype.getUTCSeconds()
Date.prototype.getYear()