How to import ion-rangeslider in Aurelia - aurelia

I am trying to use the ionRangeSlider plugin in Aurelia but am not sure how to make use of it.
https://github.com/IonDen/ion.rangeSlider/issues
I have jspm'd it into my project but how do I import it as well as call the one function that runs the plugin?

You will find the exact package names for including ion-rangesider in your package.json:
jspm": {
"dependencies": {
...
"ion-rangeslider": "npm:ion-rangeslider#^2.1.3",
"jquery": "npm:jquery#^2.2.3",
...
}
}
Then you need to create your own custom element like:
import {inject, noView} from 'aurelia-framework';
//import your dependencies
import $ from 'jquery';
import ionRangeSlider from 'ion-rangeslider';
#noView()
#inject(Element)
export class Slider {
constructor(element){
this.element = element;
}
bind(){
$(this.element).ionRangeSlider({min: 100, max: 1000, from: 550});
}
}
And where you want to use your slider you have to write:
<require from='./slider'></require>
<require from="ion-rangeslider/css/ion.rangeSlider.skinHTML5.css"></require>
<require from="ion-rangeslider/css/ion.rangeSlider.css"></require>
<slider></slider>
Normally you would put the <require from="xxx.css"></require> tags inside slider.html to ensure style encapsulation. In my example i put them where i wanted to use the slider because so i donĀ“t needed to create a slider.html.

Here is an example how to use the bootstrap popover.
I guess you should be able to do the same and calling $("#example_id").ionRangeSlider(); from within the bind function
if you imported all resources

Install ion-rangeslider first:
npm install ion-rangeslider
jspm install npm:ion-rangeslider
Create a custom attribute
import {customAttribute, bindable, inject} from 'aurelia-framework';
import {ionRangeSlider} from 'ion-rangeslider';
#customAttribute('rangeslider')
#inject(Element)
export class RangesliderCustomAttribute {
//make your own options based on requirements
options = { type: "single", min: 0, max: 100 };
constructor(element) {
this.element = element;
}
attached() {
$(this.element).ionRangeSlider(this.options).on('change', e => {
fireEvent(e.target, 'input');
});
}
detached() {
$(this.element).ionRangeSlider('destroy').off('change');
}
}
function createEvent(name) {
var event = document.createEvent('Event');
event.initEvent(name, true, true);
return event;
}
function fireEvent(element, name) {
var event = createEvent(name);
element.dispatchEvent(event);
}
import css into app.html or where you import css in your application
<require from="ion-rangeslider/css/ion.rangeSlider.css"></require>
<require from="ion-rangeslider/css/ion.rangeSlider.skinNice.css"></require>
Now you can use your attribute in input in any view
<require from="./rangeslider"></require>
<input rangeslider type="text" value.bind="yourInitialSliderValue">

Related

How to fix #ViewChild ElementRef undefined in NativeScript Angular?

I am developing a mobile application with NativeScript (CLI v5.2.0) Angular (v7.2.3) and I have my #ViewChild ElementRef that was undefined.
I checked the presence of ViewChild and ElementRef in the import of "#angular/core", renamed my #ViewChild variable, changed the scope from public to private, moved the console.log() in ngAfterViewInit (see: https://github.com/NativeScript/nativescript-angular/issues/188#issuecomment-212815619) and rebuilt my project with "tns debug android --clean --bundle".
component-name.component.ts :
#ViewChild("test") private _scrollView: ElementRef;
constructor(page: Page) {
page.actionBarHidden = true;
}
ngAfterViewInit() {
console.log("ScrollView element:", this._scrollView.nativeElement);
}
...
component-name.component.html :
<GridLayout columns="*" rows="*, auto">
<ScrollView (swipe)="onSwipe($event)" col="0" row="0" #test>
<StackLayout>
...
If I put #test at the beginning, just after the ScrollView element, I have "this._scollView" variable that is undefined.
If I put #test at the end, like the example above, everything works and I show my element in the console.log(this._scrollView.nativeElement)!
A bug ?
Previous code:
import { ElementRef } from "#angular/core";
#ViewChild("myElement") myElement: ElementRef;
Migrated code:
import { ElementRef } from "#angular/core";
#ViewChild("myElement", { static: false }) myElement: ElementRef;
{static: false} means nfAfterInit,
{static: true} mean ngInit
its works for me.

ion-slides methods not working in ionic 4

Unable to use methods provided by ion-slides in official documentation. checked other answers in here but all seems to confuse ionic 4 with ionic 3 and providing answers applicable in ionic 3.
I want to get active index of slide. online documentation is not complete about how to implement it.
Note: Use IonSlides and don't use ElementRef and nativeElement
Just follow the code below and it will work fine to get the active index from getActiveIndex()
import { IonSlides } from '#ionic/angular';
#ViewChild('slides', {static: true}) slides: IonSlides;
slideChanged(e: any) {
this.slides.getActiveIndex().then((index: number) => {
console.log(index);
});
}
In ionic 4, the return type of the getActiveIndex() method is Promise<number>, so the code you were using in ionic 3 will not work anymore. You could at a bare minimum switch it out for somehting like:
this.slider.getActiveIndex()
.then(activeIndex => {
console.log('active index = ', activeIndex );
if (activeIndex < this.slides.length) {
this.selectedSegment = this.slides[activeIndex ].id;
}
});
Or whatever you want to use it for. The official doc is actually pretty awesome on this: https://ionicframework.com/docs/api/slides
Build the slider in your html with a slides ID and a function which is emitted when the active slide has changed.
<ion-slides #slides (ionSlideDidChange)="getIndex()">
<ion-slide></ion-slide>
</ion-slides>
In the .ts file you import the slider ID with ViewChild and set the function to get the active index.
import { Component, OnInit, ViewChild } from '#angular/core';
import { Slides } from '#ionic/angular';
export class Page implements OnInit {
#ViewChild('slides') slides: Slides;
constructor() {}
ngOnInit() {
}
async getIndex() {
console.log(await this.slides.getActiveIndex());
}
}
I had the same issue, but I solved it with the following code:
My .ts file:
export class RegistroPage implements OnInit {
#ViewChild('registroWizard') registroWizard: IonSlides;
slideOpts: any;
constructor() {
this.slideOpts = {
effect: 'fade'
};
}
ngOnInit() {
this.registroWizard.lockSwipeToNext(true);
}
}
My HTML file:
<ion-slides #registroWizard pager="true" [options]="slideOpts">
<ion-slide>
<h1>Slide 1</h1>
<ion-button>Hola</ion-button>
</ion-slide>
<ion-slide>
<h1>Slide 2</h1>
<ion-button>Hola</ion-button>
</ion-slide>
<ion-slide>
<h1>Slide 3</h1>
<ion-button>Hola</ion-button>
</ion-slide>
</ion-slides>
I solved the problem like this:
page.ts:
import { IonSlides } from '#ionic/angular';
...
#ViewChild('slides') slides: IonSlides;
nextSlide() {
this.slides.slideNext();
}
page.html:
<ion-slides #slides pager="true" [options]="slideOpts">
<ion-slide>slide 1</ion-slide>
<ion-slide>slide 2</ion-slide>
</ion-slides>
<ion-button (click)="nextSlide()" class="register-buttons">go next</ion-button>
exact the same thing goes for the back action
static: true
#ViewChild('ionSlides', { static: true }) ionSlides: IonSlides;
u need declaration class to app.module.ts
#NgModule({
declarations: [MySliderComponent]
})
I used IonSlides as type but it didn't help.
For me, the above mentioned solutions didnt work (ionic v6.17.1). What worked was:
#ViewChild('slides', {static: true}) slides: ElementRef;
swipeRight() {
this.slides.nativeElement.slideNext();
All methods working this way. Altering ```{static: true} didn't throw any error
If you console.log after declaring slides as IonSlides type, it shows ElementRef type

Get ng-template from component angular 2

how can i get the element in angular 2?
in case i have this in html
<ng-template #content let-c="close" let-d="dismiss">
<div class="modal-header">Header</div>
<div class="modal-body">Body</div>
<div class="modal-footer">footer</div>
</ng-template>
i use that for ngBmodal ng-bootstrap
if i use button for open content its work = button
(click)="open(content,data.id)"
then i would like open content from component
in this case, im redirect from other page and open content
ngOnInit() {
this.activatedRoute.queryParams.subscribe((params: Params) => {
let id = params['id'];
if(id != undefined){
this.open('content',id);
}
});
}
open(content, id) {
this.dataModal = {};
this.getDataModal(id);
this.mr = this.modalService.open(content, { size: 'lg' });
}
modal open but not with the html, i try afterviewinit to get #content it doesnt work
thanks,sorry for my english :v
First import NgbModal and ModalDismissReasons
import { NgbModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
and add modalservice to constructor
private modalService: NgbModal
See:
https://ng-bootstrap.github.io/#/components/modal/examples#options
Then in your typescript file:
1 - Import TemplateRef and ViewChild, example:
import { TemplateRef, ViewChild } from '#angular/core';
2 - Create the variable that binds the ngtemplate (add before constructor):
#ViewChild('content')
private content: TemplateRef<any>;
3 - Open modal from typescript:
this.modalService.open(this.content);

Organizing global functions in aurelia

I have a function that I'd like to use in several of my ViewModels. It's a filter function that I use as a param for a custom filter:
<tr repeat.for="server of servers | filter:searchTerm:filterFunc">
What is the "aurelic" way of storing functions like this? I'm very new to both js and aurelia, so an easy-to-understand "non-minified" example would make me super-grateful :-)
EDIT: For reference, I stuck the function inside my ValueConverter class since it will only be used in conjunction with it.
export class filterValueConverter {
myCustomFunc(stuf,stuf){}
toView(array, searchTerm){return this.myCustomFunc}}
You would probably need to create a value converter for an array to do this.
Html in view(s):
<div repeat.for="item of [1, null, 2] | notNullFilter">${item}</div>
Filter (src\resources\value-converters\notNullFilterValueConverter.js):
export class notNullFilterValueConverter {
toView(array) {
return array.filter(item => item !== null);
}
}
And register it as global resource in your main.js setup:
import {Aurelia} from 'aurelia-framework';
export function configure(aurelia: Aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging()
.globalResources([
"./src/resources/value-converters/notNullFilterValueConverter"
]);
aurelia.start().then(() => aurelia.setRoot());
}
You can just insert any number of value converters in the array you give to the global resources function.
Which will output
<div>1</div>
<div>2</div>
If at some stage this becomes clouded/ messy, you could move it to a feature:
export function configure(aurelia: Aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging()
.feature('resources');
aurelia.start().then(function () { return aurelia.setRoot('views/app'); });
}
Add a folder named 'resources' with a file inside index.js
export function configure(config) {
config.globalResources('./notNullFilterValueConverter', './welcomeValueConverter');
}
A 'feature' is the same as a plugin with the only difference that it is living in your source tree. It allows you to make multiple features, so there could be for example one called company-array-filters and one custom-company-elements.

Aurelia dialog not getting the view easy-webpack skeleton

Somehow when I let the framework load dialog view automatically, it said:
Failed to load view exception
However, when using inlineView it works as expected.
How can I make it load the view ?
It's a little late, but it may be useful for other users.
This error is because Webpack loader.
More info where: https://github.com/aurelia/dialog/issues/127
I don't like using string to reference the dialog ViewModel, because this I suggest using the option to force the View in dialog ViewModel. I don't have to change anything else.
Example:
Dialog ViewModel:
import {autoinject, useView} from 'aurelia-framework';
import {DialogController} from 'aurelia-dialog';
#autoinject()
#useView('./dialog-message.html') //This is the important line!!!!!
export class DialogMessage {
message: string = 'Default message for dialog';
constructor(private controller: DialogController){
controller.settings.centerHorizontalOnly = true;
}
activate(message) {
this.message = message;
}
}
Dialog View:
<template>
<ai-dialog>
<ai-dialog-body>
<h2>${message}</h2>
</ai-dialog-body>
<ai-dialog-footer>
<button click.trigger = "controller.cancel()">Cancel</button>
<button click.trigger = "controller.ok(message)">Ok</button>
</ai-dialog-footer>
</ai-dialog>
</template>
Method to show Dialog:
import {DialogMessage} from './dialog-message';
(...)
showDialog(){
this.dialogService.open({viewModel: DialogMessage, model: 'Hi, how are you?' }).then(response => {
if (!response.wasCancelled) {
console.log('good');
} else {
console.log('bad');
}
console.log(response.output);
});
}