Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 4d535e2

Browse files
zbjornsonThomasBurleson
authored andcommitted
feat($mdDialog): add prompt
Add preconfigured dialog for prompt. Fixes #4995. Closes #6769.
1 parent 3f41ae2 commit 4d535e2

File tree

5 files changed

+182
-4
lines changed

5 files changed

+182
-4
lines changed

src/components/dialog/demoBasicUsage/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
<md-button class="md-primary md-raised" ng-click="showConfirm($event)" flex="100" flex-gt-md="auto">
1212
Confirm Dialog
1313
</md-button>
14+
<md-button class="md-primary md-raised" ng-click="showPrompt($event)" flex="100" flex-gt-md="auto">
15+
Prompt Dialog
16+
</md-button>
1417
<md-button class="md-primary md-raised" ng-click="showAdvanced($event)" flex="100" flex-gt-md="auto">
1518
Custom Dialog
1619
</md-button>

src/components/dialog/demoBasicUsage/script.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,24 @@ angular.module('dialogDemo1', ['ngMaterial'])
3737
});
3838
};
3939

40+
$scope.showPrompt = function(ev) {
41+
// Appending dialog to document.body to cover sidenav in docs app
42+
var confirm = $mdDialog.prompt()
43+
.title('What would you name your dog?')
44+
.textContent('Bowser is a common name.')
45+
.placeholder('dog name')
46+
.ariaLabel('Dog name')
47+
.targetEvent(ev)
48+
.ok('Okay!')
49+
.cancel('I\'m a cat person');
50+
51+
$mdDialog.show(confirm).then(function(result) {
52+
$scope.status = 'You decided to name your dog ' + result + '.';
53+
}, function() {
54+
$scope.status = 'You didn\'t name your dog.';
55+
});
56+
};
57+
4058
$scope.showAdvanced = function(ev) {
4159
var useFullScreen = ($mdMedia('sm') || $mdMedia('xs')) && $scope.customFullscreen;
4260

src/components/dialog/dialog.js

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,32 @@ function MdDialogDirective($$rAF, $mdTheming, $mdDialog) {
364364
*
365365
*/
366366

367+
/**
368+
* @ngdoc method
369+
* @name $mdDialog#prompt
370+
*
371+
* @description
372+
* Builds a preconfigured dialog with the specified message and input box. You can call show and the promise returned
373+
* will be resolved only if the user clicks the prompt action on the dialog, passing the input value as the first argument.
374+
*
375+
* @returns {obj} an `$mdDialogPreset` with the chainable configuration methods:
376+
*
377+
* Additionally, it supports the following methods:
378+
*
379+
* - $mdDialogPreset#title(string) - Sets the prompt title.
380+
* - $mdDialogPreset#textContent(string) - Sets the prompt message.
381+
* - $mdDialogPreset#htmlContent(string) - Sets the prompt message as HTML. Requires ngSanitize
382+
* module to be loaded. HTML is not run through Angular's compiler.
383+
* - $mdDialogPreset#placeholder(string) - Sets the placeholder text for the input.
384+
* - $mdDialogPreset#ok(string) - Sets the prompt "Okay" button text.
385+
* - $mdDialogPreset#cancel(string) - Sets the prompt "Cancel" button text.
386+
* - $mdDialogPreset#theme(string) - Sets the theme of the prompt dialog.
387+
* - $mdDialogPreset#targetEvent(DOMClickEvent=) - A click's event object. When passed in as an option,
388+
* the location of the click will be used as the starting point for the opening animation
389+
* of the the dialog.
390+
*
391+
*/
392+
367393
/**
368394
* @ngdoc method
369395
* @name $mdDialog#show
@@ -472,10 +498,15 @@ function MdDialogProvider($$interimElementProvider) {
472498
methods: ['title', 'htmlContent', 'textContent', 'content', 'ariaLabel', 'ok', 'cancel',
473499
'theme', 'css'],
474500
options: advancedDialogOptions
501+
})
502+
.addPreset('prompt', {
503+
methods: ['title', 'htmlContent', 'textContent', 'content', 'placeholder', 'ariaLabel',
504+
'ok', 'cancel', 'theme', 'css'],
505+
options: advancedDialogOptions
475506
});
476507

477508
/* @ngInject */
478-
function advancedDialogOptions($mdDialog, $mdTheming) {
509+
function advancedDialogOptions($mdDialog, $mdTheming, $mdConstant) {
479510
return {
480511
template: [
481512
'<md-dialog md-theme="{{ dialog.theme }}" aria-label="{{ dialog.ariaLabel }}" ng-class="dialog.css">',
@@ -486,25 +517,33 @@ function MdDialogProvider($$interimElementProvider) {
486517
' <div ng-if="::!dialog.mdHtmlContent" class="md-dialog-content-body">',
487518
' <p>{{::dialog.mdTextContent}}</p>',
488519
' </div>',
520+
' <md-input-container md-no-float ng-if="::dialog.$type == \'prompt\'" class="md-prompt-input-container">',
521+
' <input ng-keypress="dialog.keypress($event)" md-autofocus ng-model="dialog.result" placeholder="{{::dialog.placeholder}}">',
522+
' </md-input-container>',
489523
' </md-dialog-content>',
490524
' <md-dialog-actions>',
491-
' <md-button ng-if="dialog.$type == \'confirm\'"' +
525+
' <md-button ng-if="dialog.$type === \'confirm\' || dialog.$type === \'prompt\'"' +
492526
' ng-click="dialog.abort()" class="md-primary">',
493527
' {{ dialog.cancel }}',
494528
' </md-button>',
495-
' <md-button ng-click="dialog.hide()" class="md-primary" md-autofocus="dialog.$type!=\'confirm\'">',
529+
' <md-button ng-click="dialog.hide()" class="md-primary" md-autofocus="dialog.$type===\'alert\'">',
496530
' {{ dialog.ok }}',
497531
' </md-button>',
498532
' </md-dialog-actions>',
499533
'</md-dialog>'
500534
].join('').replace(/\s\s+/g, ''),
501535
controller: function mdDialogCtrl() {
502536
this.hide = function() {
503-
$mdDialog.hide(true);
537+
$mdDialog.hide(this.$type === 'prompt' ? this.result : true);
504538
};
505539
this.abort = function() {
506540
$mdDialog.cancel();
507541
};
542+
this.keypress = function($event) {
543+
if ($event.keyCode === $mdConstant.KEY_CODE.ENTER) {
544+
$mdDialog.hide(this.result)
545+
}
546+
}
508547
},
509548
controllerAs: 'dialog',
510549
bindToController: true,

src/components/dialog/dialog.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ md-dialog {
8484
.md-dialog-content-body {
8585
width:100%;
8686
}
87+
88+
.md-prompt-input-container {
89+
width: 100%;
90+
box-sizing: border-box;
91+
}
8792
}
8893

8994
.md-actions, md-dialog-actions {

src/components/dialog/dialog.spec.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,119 @@ describe('$mdDialog', function() {
486486
}));
487487
});
488488

489+
describe('#prompt()', function() {
490+
hasConfigurationMethods('prompt', ['title', 'htmlContent', 'textContent',
491+
'content', 'placeholder', 'ariaLabel', 'ok', 'cancel', 'theme', 'css'
492+
]);
493+
494+
it('shows a basic prompt dialog', inject(function($animate, $rootScope, $mdDialog) {
495+
var parent = angular.element('<div>');
496+
var resolved = false;
497+
var promptAnswer;
498+
499+
$mdDialog.show(
500+
$mdDialog
501+
.prompt()
502+
.parent(parent)
503+
.title('Title')
504+
.textContent('Hello world')
505+
.placeholder('placeholder text')
506+
.theme('some-theme')
507+
.css('someClass anotherClass')
508+
.ok('Next')
509+
.cancel('Cancel')
510+
).then(function(answer) {
511+
resolved = true;
512+
promptAnswer = answer;
513+
});
514+
515+
$rootScope.$apply();
516+
runAnimation();
517+
518+
var mdContainer = angular.element(parent[0].querySelector('.md-dialog-container'));
519+
var mdDialog = mdContainer.find('md-dialog');
520+
var mdContent = mdDialog.find('md-dialog-content');
521+
var title = mdContent.find('h2');
522+
var contentBody = mdContent[0].querySelector('.md-dialog-content-body');
523+
var inputElement = mdContent.find('input');
524+
var buttons = parent.find('md-button');
525+
var theme = mdDialog.attr('md-theme');
526+
var css = mdDialog.attr('class').split(' ');
527+
528+
expect(title.text()).toBe('Title');
529+
expect(contentBody.textContent).toBe('Hello world');
530+
expect(inputElement[0].placeholder).toBe('placeholder text')
531+
expect(buttons.length).toBe(2);
532+
expect(buttons.eq(0).text()).toBe('Next');
533+
expect(theme).toBe('some-theme');
534+
expect(css).toContain('someClass');
535+
expect(css).toContain('anotherClass');
536+
expect(mdDialog.attr('role')).toBe('dialog');
537+
538+
inputElement.eq(0).text('responsetext');
539+
inputElement.scope().$apply("dialog.result = 'responsetext'")
540+
541+
buttons.eq(0).triggerHandler('click');
542+
543+
$rootScope.$apply();
544+
runAnimation();
545+
546+
expect(resolved).toBe(true);
547+
expect(promptAnswer).toBe('responsetext');
548+
}));
549+
550+
it('should focus the input element on open', inject(function($mdDialog, $rootScope, $document) {
551+
jasmine.mockElementFocus(this);
552+
553+
var parent = angular.element('<div>');
554+
555+
$mdDialog.show(
556+
$mdDialog
557+
.prompt()
558+
.parent(parent)
559+
.textContent('Hello world')
560+
.placeholder('placeholder text')
561+
)
562+
563+
runAnimation(parent.find('md-dialog'));
564+
565+
expect($document.activeElement).toBe(parent[0].querySelector('input'));
566+
}));
567+
568+
it('should submit after ENTER key', inject(function($mdDialog, $rootScope, $timeout, $mdConstant) {
569+
jasmine.mockElementFocus(this);
570+
var parent = angular.element('<div>');
571+
var response;
572+
573+
$mdDialog.show(
574+
$mdDialog
575+
.prompt()
576+
.parent(parent)
577+
.textContent('Hello world')
578+
.placeholder('placeholder text')
579+
).then(function(answer) {
580+
response = answer;
581+
});
582+
runAnimation();
583+
584+
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
585+
var mdDialog = container.find('md-dialog');
586+
var mdContent = mdDialog.find('md-dialog-content');
587+
var inputElement = mdContent.find('input');
588+
589+
inputElement.scope().$apply("dialog.result = 'responsetext'")
590+
591+
inputElement.eq(0).triggerHandler({
592+
type: 'keypress',
593+
keyCode: $mdConstant.KEY_CODE.ENTER
594+
});
595+
runAnimation();
596+
runAnimation();
597+
598+
expect(response).toBe('responsetext');
599+
}));
600+
});
601+
489602
describe('#build()', function() {
490603
it('should support onShowing callbacks before `show()` starts', inject(function($mdDialog, $rootScope) {
491604

0 commit comments

Comments
 (0)