feat(alert): iOS radio button alert

Related #890
This commit is contained in:
Adam Bradley
2016-01-07 17:03:38 -06:00
parent 387f883be3
commit 0d695546e5
4 changed files with 142 additions and 17 deletions

View File

@ -81,6 +81,46 @@ ion-alert {
-webkit-appearance: none;
}
.alert-radio {
display: flex;
min-height: $alert-ios-button-min-height;
border-top: 1px solid $alert-ios-button-border-color;
cursor: pointer;
&[aria-checked=true] {
color: $alert-ios-button-text-color;
.alert-radio-icon:after {
position: absolute;
border-width: 2px;
border-style: solid;
border-color: $alert-ios-button-text-color;
top: 13px;
left: 7px;
width: 4px;
height: 10px;
border-left: none;
border-top: none;
content: '';
transform: rotate(45deg);
}
}
}
.alert-radio-label {
flex: 1;
order: 0;
text-align: auto;
padding: 13px;
}
.alert-radio-icon {
position: relative;
order: 1;
min-width: 30px;
}
.alert-button {
margin: 0;
flex: 1;

View File

@ -1,5 +1,5 @@
import {Component, ElementRef, Renderer} from 'angular2/core';
import {NgClass, NgIf, NgFor} from 'angular2/common';
import {NgClass, NgSwitch, NgIf, NgFor} from 'angular2/common';
import {NavParams} from '../nav/nav-controller';
import {ViewController} from '../nav/view-controller';
@ -183,13 +183,30 @@ export class Alert extends ViewController {
'<h3 class="alert-sub-title" *ngIf="d.subTitle">{{d.subTitle}}</h3>' +
'</div>' +
'<div class="alert-body" *ngIf="d.body">{{d.body}}</div>' +
'<div class="alert-body alert-inputs" *ngIf="d.inputs.length">' +
'<div class="alert-input-wrapper" *ngFor="#i of d.inputs">' +
'<input [placeholder]="i.placeholder" [(ngModel)]="i.value" [type]="i.type" class="alert-input">' +
'</div>' +
'<div *ngIf="d.inputs.length" [ngSwitch]="inputType">' +
'<template ngSwitchWhen="radio">' +
'<div class="alert-radio-group">' +
'<div *ngFor="#i of d.inputs" (click)="rbClick(i)" [attr.aria-checked]="i.checked" class="alert-radio" tappable role="radio">' +
'<div class="alert-radio-icon"></div>' +
'<div class="alert-radio-label">' +
'{{i.label}}' +
'</div>' +
'</div>' +
'</div>' +
'</template>' +
'<template ngSwitchDefault>' +
'<div class="alert-body alert-inputs">' +
'<div *ngFor="#i of d.inputs" class="alert-input-wrapper">' +
'<input [placeholder]="i.placeholder" [(ngModel)]="i.value" [type]="i.type" class="alert-input">' +
'</div>' +
'</div>' +
'</template>' +
'</div>' +
'<div class="alert-buttons">' +
'<button *ngFor="#b of d.buttons" (click)="click(b)" [ngClass]="b.cssClass" class="alert-button">' +
'<button *ngFor="#b of d.buttons" (click)="btnClick(b)" [ngClass]="b.cssClass" class="alert-button">' +
'{{b.text}}' +
'</button>' +
'</div>' +
@ -197,7 +214,7 @@ export class Alert extends ViewController {
host: {
'role': 'dialog'
},
directives: [NgClass, NgIf, NgFor]
directives: [NgClass, NgSwitch, NgIf, NgFor]
})
class AlertCmp {
@ -214,7 +231,7 @@ class AlertCmp {
}
}
click(button) {
btnClick(button) {
let shouldDismiss = true;
if (button.handler) {
@ -233,11 +250,32 @@ class AlertCmp {
}
}
rbClick(checkedInput) {
this.d.inputs.forEach(input => {
input.checked = (checkedInput === input);
});
if (!this.d.buttons.length) {
// auto dismiss if no buttons
setTimeout(() => {
this.dismiss();
}, this._config.get('pageTransitionDelay'));
}
}
dismiss() {
this._viewCtrl.dismiss(this.getValues());
}
getValues() {
if (this.inputType === 'radio') {
// this is a radio button alert
// return the one radio button value which is checked
let checkedInput = this.d.inputs.find(input => input.checked);
return checkedInput ? checkedInput.value : undefined;
}
// return an object of all the values with the name as the key
let values = {};
this.d.inputs.forEach(input => {
values[input.name] = input.value;
@ -247,22 +285,28 @@ class AlertCmp {
onPageLoaded() {
// normalize the data
this.d.buttons = this.d.buttons.map(button => {
let data = this.d;
data.buttons = data.buttons.map(button => {
if (typeof button === 'string') {
return { text: button };
}
return button;
});
this.d.inputs = this.d.inputs.map((input, index) => {
data.inputs = data.inputs.map((input, index) => {
return {
type: input.type || 'text',
name: isDefined(input.name) ? input.name : index,
placeholder: isDefined(input.placeholder) ? input.placeholder : '',
type: input.type || 'text',
value: isDefined(input.value) ? input.value : ''
}
value: isDefined(input.value) ? input.value : '',
label: input.label,
checked: !!input.checked,
};
});
this.inputType = (data.inputs.length ? data.inputs[0].type : null);
let self = this;
self.keyUp = function(ev) {
if (ev.keyCode === 13) {

View File

@ -68,7 +68,7 @@ class E2EPage {
setTimeout(() => {
console.log('Prompt close');
alert.close(data);
alert.dismiss(data);
}, 500);
return false;
@ -92,6 +92,44 @@ class E2EPage {
});
}
doRadio() {
let alert = Alert.create();
alert.setTitle('Radio!');
alert.addInput({
type: 'radio',
label: 'Radio 1',
value: 'value1',
checked: true
});
alert.addInput({
type: 'radio',
label: 'Radio 2',
value: 'value2'
});
alert.addInput({
type: 'radio',
label: 'Radio 3',
value: 'value3'
});
alert.addButton('Cancel');
alert.addButton({
text: 'Ok',
handler: data => {
console.log('Select data:', data);
this.testRadioOpen = false;
this.testRadioResult = data;
}
});
this.nav.present(alert).then(() => {
this.testRadioOpen = true;
});
}
}

View File

@ -5,15 +5,18 @@
<ion-content padding>
<button class="e2eOpenAlert" (click)="doAlert()">Alert</button>
<button class="e2eOpenConfirm" (click)="doConfirm()">Confirm</button>
<button class="e2eOpenPrompt" (click)="doPrompt()">Prompt</button>
<button block class="e2eOpenAlert" (click)="doAlert()">Alert</button>
<button block class="e2eOpenConfirm" (click)="doConfirm()">Confirm</button>
<button block class="e2eOpenPrompt" (click)="doPrompt()">Prompt</button>
<button block class="e2eOpenRadio" (click)="doRadio()">Radio</button>
<pre>
Confirm Opened: {{testConfirmOpen}}
Confirm Result: {{testConfirmResult}}
Prompt Opened: {{testPromptOpen}}
Prompt Result: {{testPromptResult | json}}
Radio Opened: {{testRadioOpen}}
Radio Result: {{testRadioResult}}
</pre>
</ion-content>