I'm trying to make an app for class attendance. So, I need to show a calendar in which student's attendance can be shown whether they were present or absent on that specific day. Is there any workaround to directly show a calendar and perform functions on it.
Screenshot of how it's supposed to look:
you need to use plugin called ionic2-calender then use do this steps
1) add ionic2-calender module to app.module.ts
import { NgCalendarModule } from 'ionic2-calendar';
#NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(),
AppRoutingModule, NgCalendarModule],
})
export class AppModule {}
2) declare it in the page module .ts file as well same as above.
3) then add .html
<ion-content>
<calendar [eventSource]="eventSource" [markDisabled]="markDisabled"
[calendarMode]="calendar.mode" [currentDate]="calendar.currentDate"
(onCurrentDateChanged)="onCurrentDateChanged($event)"
(onEventSelected)="onEventSelected($event)"
(onTitleChanged)="onViewTitleChanged($event)"
(onTimeSelected)="onTimeSelected($event)" step="30">
</calendar>
</ion-content>
4)then use event as per your requiremnt in page.ts file.
export class HomePage {
public eventSource = [];
public selectedDate = new Date();
isToday: boolean = true;
markDisabled = (date: Date) => {
var d = new Date();
// d.setDate(d.getDate() - 1);
return date < d;
};
calendar = {
mode: 'month',
currentDate: this.selectedDate
}
constructor(public navCtrl: NavController) {
}
changeMode(mode) {
this.calendar.mode = mode;
}
loadEvents() {
this.eventSource = this.createRandomEvents();
}
onCurrentDateChanged(ev) {
console.log(ev);
var today = new Date();
today.setHours(0, 0, 0, 0);
ev.setHours(0, 0, 0, 0);
this.isToday = today.getTime() === ev.getTime();
}
onViewTitleChanged(Title) {
this.viewTitle = Title;
}
onTimeSelected(event) {
console.log(event);
var date = new Date().getTime();
console.log(date);
var task = "work fast";
}
onEventSelected(event) {
console.log(event);
}
this is working example I have implimented in my ionic4 project.if you don't undestand this answer then please check videos tutorial of ionic2-calender
The problem of "can't bind event Source in calendar element" is due to problem of lazy loading. Please try importing calendar module in your respective page.module.ts file.
Related
I´m developing an Ionic 4 aplication and I want to usea a custom side menu animation like this:
but Ionic only have 3 options: push, overlay and reveal.
I already have my 3dmenu.ts file but I don´t no how to inject it to use It with the Ion-menu componet like the other 3 options, could some one give a hint about how to do this?
I finally can do it, Using workaruond than I found here here. The trick is extend the menu controller class to create a new method registerAnimation:
Step 1: Create a new ts file (extended.ts or the name than you want) and put this code inside:
import { DOCUMENT } from '#angular/common';
import { Inject, Injectable } from '#angular/core';
import { MenuController } from '#ionic/angular';
import { AnimationBuilder } from '#ionic/core';
function proxyMethod(ctrlName: string, doc: Document, methodName: string, ...args: any[]) {
const controller = ensureElementInBody(ctrlName, doc);
return controller.componentOnReady()
.then(() => (controller as any)[methodName].apply(controller, args));
}
function ensureElementInBody(elementName: string, doc: Document) {
let element = doc.querySelector(elementName);
if (!element) {
element = doc.createElement(elementName);
doc.body.appendChild(element);
}
return element as HTMLStencilElement;
}
const CTRL = 'ion-menu-controller';
#Injectable({
providedIn: 'root',
})
export class EloMenuController extends MenuController {
constructor(#Inject(DOCUMENT) private document: any) {
super(document)
}
/**
* Registers a new animation that can be used with any `ion-menu` by
* passing the name of the animation in its `type` property.
*
* #param name The name of the animation to register.
* #param animation The animation function to register.
*/
registerAnimation(name: string, animation: AnimationBuilder) {
return proxyMethod(CTRL, this.document, 'registerAnimation', name, animation);
}
}
Step 2: Create a new ts file with the animation, in my case I use this:
import { Animation, MenuI } from '#ionic/core';
export function menu3D (AnimationC: Animation, baseEl: HTMLElement, menu: MenuI):
Promise<Animation> {
let contentOpenedX: string;
let menuClosedX: string;
const width = menu.width;
const baseAnimation = new AnimationC();
if (menu.isEndSide) {
contentOpenedX = -width + 'px';
menuClosedX = width + 'px';
}
else {
contentOpenedX = width + 'px';
menuClosedX = -width + 'px';
}
const menuAnimation = new AnimationC()
.addElement(menu.menuInnerEl)
.fromTo('z-index', '0', '0')
.fromTo('translateX', menuClosedX, '0px');
const contentAnimation = new AnimationC()
.addElement(menu.contentEl)
.fromTo('translateX', '0px', contentOpenedX)
.fromTo('scale', '1', '0.7');
const backdropAnimation = new AnimationC()
.addElement(menu.backdropEl)
.fromTo('opacity', 0.01, 0.32);
return Promise.resolve(baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(0.0, 0.0, 0.2, 1)')
.easingReverse('cubic-bezier(0.4, 0.0, 0.6, 1)')
.duration(300)
.add(contentAnimation)
.add(menuAnimation)
.add(backdropAnimation));
};
Step 3: import in your app.component.ts the extended class and the animation and register your animation to be able to use it:
import { Component, OnInit, Input } from '#angular/core';
import { Extend } from './animations/extend
import { menu3D } from './animations/menu3D';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html',
})
export class AppComponent implements OnInit {
#Input() name: string;
constructor(
private menu: Extend
) {
this.menu.registerAnimation('menu3d', menu3D);
}
ngOnInit() {}
}
Step 4: configure the type to your ion-menu component
<ion-menu side="start" type="menu3d" style="z-index: 10;">
........
</ion-menu>
Step 5: Don't forget to thanks to svallory from github and Enjoy it :-)
I don´t konw if it this the best way to do it but its the only way than I found after 5 days searching, I hope this helps other and if anyone can improve this feel free to comment :-)
I am working on an ionic project.
I need to use the InAppBrowser plugin to display a website.
But depending on which page I am, I need to change the view to an Ionic page.
export class HomePage {
constructor(public navCtrl: NavController, public inAppBrowser: InAppBrowser, public platform: Platform) {
var url = "https://helloworld.com";
var browser = inAppBrowser.create(url, '_blank', {
zoom: 'no',
location: 'no'
});
platform.ready().then(() => {
browser.show();
browser.on('loadstart').subscribe((e) => {
var navCtlr = this.navCtrl;
var scriptUrlParam = "window.addEventListener(\"click\",function(e){var href=e.target.getAttribute(\"href\");if(href){location.href=href+\"?source=mobapp\";e.preventDefault();}});";
var url = e.url;
if (url.indexOf("scanner") !== -1) {
alert("Page Scanner");
navCtrl.push(QrcodePage);
}
browser.insertCSS({
code: "#mobileMenu{display:block!important;}"
});
browser.executeScript({
code: scriptUrlParam
});
});
});
}
}
navCtrl.push(QrcodePage); is supposed to redirect me to the QR Code page. But it doesn't work.
I know I am on the right page because alert("Page Scanner"); is working.
Have anyone occurred this probleme already ?
Thanks
I build a simple page and it renders a list of some items. These items have a href element to open it in browser. The trouble is that when user comes back all the class used to hold local variable gets reinitialized and breaks the app functionality. What is the correct way to handle this. I want to retain the data set. Below is my code for list and the variables in a service class
<ion-content>
<div class="full-screen-bg">
<div *ngFor="let alb of core.albums">
<ion-row><ion-col no-padding text-center><img src="{{alb.image}}"></ion-col></ion-row>
<ion-row><ion-col class="sg-title-text">{{alb.name}}</ion-col></ion-row>
</div>
the service class that has variables and gets reset is
#Injectable({
providedIn: 'root'
})
export class CoreService {
loggedIn:boolean
name:string
constructor(public admob: Admob,
public sgSvc:DataServiceService) {
this.loggedIn = false
console.log("album constructor called:::" + this.loggedIn + " name:" + this.name)
}
}
The simple way is save login user (username, token and expiration time) by StorageService, and for your CoreService should be try get it from StorageService and confirm it, if token is none or already over exporation time then it is mean user should be login again.
export class CoreService {
//...
public isAdmin = false;
private token = false;
public userSubject: Subject<Object> = new Subject<Object>();
//...
constructor(/*...*/) {
this.userSubject.subscribe(user => {
if (user && user['role']) {
if (user['role'] == 'admin') {
this.isAdmin = true;
} else {
this.isAdmin = false;
}
}
});
this.getLocal('user').then(val => {
this.userSubject.next(val);
});
}
//...
}
//And for other component also subscribe same subject like
export class AppComponent /*...*/ {
constructor(coreService: CoreService /*...*/) {
this.coreService.userSubject.subscribe(user => {
// your logic there
});
}
}
I created a dynamic form following the instructions in the angular cookbook and then I've tried to create the form with metadata that I have in my database.
I made an HTTP request to the get field types, names, ids, etc. but when I try to build the form as in the angular example, nothing happens or I get errors on console.
Here's the code from the tutorial:
export class AppComponent {
questions: any[];
constructor(service: QuestionService) {
this.questions = service.getQuestions();
}
}
And this is what I did:
export class AppComponent implements OnInit {
campos: any[] = [];
constructor(private servico: FormDadosService) {}
ngOnInit() {
this.servico.getCampos().subscribe(this.processaCampos);
}
processaCampos(dados) {
for (let i = 0; i < dados.length; i++) {
this.campos.push(new CampoBase({
nome: dados[i].ZI2_NOME,
label: dados[i].ZI2_DESC,
ordem: dados[i].ZI2_ORDEM,
obrigatorio: dados[i].ZI2_OBRIGAT,
tamanho: dados[i].ZI2_TAM,
valor: '',
tipoCampo: dados[i].ZI2_TIPO
}))
}
}
}
I am getting this error:
error_handler.js:50EXCEPTION: Cannot read property 'push' of undefined
I think I need to know a way to render the form after all data about it has arrived from my HTTP request.
I made it work this way:
export class AppComponent implements OnInit {
campos: any[] = [];
constructor(private servico: FormDadosService) { }
ngOnInit() {
this.servico.getCampos().subscribe((data) => {
data.forEach(campo => {
this.campos.push(new CampoBase({
valor: '',
nome: campo.ZI2_CAMPO,
label: campo.ZI2_DESC,
tipoCampo: campo.ZI2_TIPO,
tamanho: campo.ZI2_TAM
}))
});
});
}
}
This question can be marked as solved.
Thanks everyone.
In my Ionic 2 app, I have i have component that GET to fetch data.
i want to maker loader and dismiss it after data is ready.
i tried to look on other posts around the stack overflow but my issue is different.
i did something but the loader is forever and its not helps me.
It looks like following:
import { Component,ViewChild } from '#angular/core';
import { NavController,LoadingController,AlertController,ViewController} from 'ionic-angular';
import { Facebook } from 'ionic-native';
//import pages
import {LoginPage} from "../../pages/login/login";
import {User} from '../../models/user'
import { Storage} from '#ionic/storage';
//import provider
import { ProfileData } from '../../providers/profile-data';
import { NotesData } from '../../providers/notes-data';
import firebase from 'firebase'
import {AddNote} from "../add-note/add-note";
/*
Generated class for the NotesList page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-notes-list',
templateUrl: 'notes-list.html'
})
export class NotesList {
//facebook user
userProfile: any = null;
uid: any = null;
fireUid:any=null;
name:string=null;
photo: any =null;
user:User=null;
photos:any=null;
currentUser:any=null;
photonew:any=null;
//notes list
notes:any=null;
data:any;
pages: Array<{title: string, component: any}>;
constructor(public navCtrl: NavController,public profileData:ProfileData,private viewCtrl: ViewController,public notesData:NotesData,private loadingCtrl: LoadingController,private alertCtrl: AlertController,public storage:Storage) {
this.data={};
this.data.title="";
this.data.desc="";
}
ionViewDidLoad() {
//if i do that the loader is forever
/*
let loader = this.loadingCtrl.create({
dismissOnPageChange: true,
});
loader.present();
*/
// here i want the loader to be until the data is ready.
this.getNotesList(); //this functions not returns data so i can't do this.getNotesList().then(()=>
}
getNotesList(){
console.log("get event");
var that=this;
this.notesData.getNotesLIst().on('value', snapshot => {
let notesList= [];
snapshot.forEach( snap => {
console.log("id note"+snap.val().id);
notesList.push({
id: snap.val().id,
title: snap.val().title,
desc: snap.val().desc,
color:snap.val().color,
photo:snap.val().photo,
});
});
that.notes = notesList;
});
}
addNote(){
this.navCtrl.push(AddNote);
}
logOutFacebook(){
Facebook.logout().then((response)=>
{
this.navCtrl.push(LoginPage);
alert(JSON.stringify(response));
},(error)=>{
alert(error);
})
}
}
At first, you should show how do you implement your loading page. Is it a splash screen with cordorva? Or just as div displaying some image?
If it is a splash screen, you can add this code in your component after you get data, (it is from starter template, you can see the detail by creating a new project with ionic start):
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.
StatusBar.styleDefault();
Splashscreen.hide();
});
And, if you use a div in your index page, it is similar, you can just get that element and remove it, with pure js.
okay it succeed to do that
this is my answer
ionViewDidLoad() {
let loader = this.loadingCtrl.create({});
loader.present();
this.getNotesList().then((x) => {
if (x) loader.dismiss();
});
}
getNotesList(){
return new Promise(resolve => {
var that=this;
this.notesData.getNotesLIst().on('value', snapshot => {
let notesList= [];
snapshot.forEach( snap => {
console.log("id note"+snap.val().id);
notesList.push({
id: snap.val().id,
title: snap.val().title,
desc: snap.val().desc,
color:snap.val().color,
photo:snap.val().photo,
});
});
that.notes = notesList;
resolve(true);
});
})
}