fix(button): submit form w/ ion-button within shadow dom

Closes #14776
This commit is contained in:
Adam Bradley
2018-07-16 12:23:13 -05:00
parent 12edfa003d
commit 4ed8541579
3 changed files with 79 additions and 2 deletions

View File

@ -1,6 +1,6 @@
import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core';
import { Color, CssClassMap, Mode, RouterDirection } from '../../interface'; import { Color, CssClassMap, Mode, RouterDirection } from '../../interface';
import { openURL } from '../../utils/theme'; import { getParentNode, openURL } from '../../utils/theme';
@Component({ @Component({
@ -118,6 +118,32 @@ export class Button {
this.ionBlur.emit(); this.ionBlur.emit();
} }
onClick(ev: Event) {
if (this.type === 'submit') {
// this button wants to specifically submit a form
// climb up the dom to see if we're in a <form>
// and if so, then use JS to submit it
let node = this.el;
while ((node = getParentNode(node))) {
if (node.nodeName.toLowerCase() === 'form') {
// cool, this submit button is within a <form>, let's submit it
// prevent the button's default and stop it's propagation
ev.preventDefault();
ev.stopPropagation();
// submit the <form> via JS
(node as HTMLFormElement).submit();
break;
}
}
} else {
openURL(this.win, this.href, ev, this.routerDirection);
}
}
hostData() { hostData() {
const { buttonType, color, expand, fill, mode, shape, size, strong } = this; const { buttonType, color, expand, fill, mode, shape, size, strong } = this;
@ -150,7 +176,7 @@ export class Button {
onFocus={this.onFocus.bind(this)} onFocus={this.onFocus.bind(this)}
onKeyUp={this.onKeyUp.bind(this)} onKeyUp={this.onKeyUp.bind(this)}
onBlur={this.onBlur.bind(this)} onBlur={this.onBlur.bind(this)}
onClick={(ev) => openURL(this.win, this.href, ev, this.routerDirection)}> onClick={this.onClick.bind(this)}>
<span class="button-inner"> <span class="button-inner">
<slot name="icon-only"></slot> <slot name="icon-only"></slot>
<slot name="start"></slot> <slot name="start"></slot>

View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Button - Form</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<script src="/dist/ionic.js"></script>
<link rel="stylesheet" type="text/css" href="/css/ionic.min.css">
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Button - Form Submit</ion-title>
</ion-toolbar>
</ion-header>
<ion-content id="content" padding no-bounce text-center>
<form action="http://httpbin.org/get" method="GET">
<div>
<input name="name">
</div>
<ion-button type="submit">
Submit Form
</ion-button>
</form>
</ion-content>
</ion-app>
</body>
</html>

View File

@ -50,3 +50,13 @@ export async function openURL(win: Window, url: string|undefined, ev: Event, dir
} }
return Promise.resolve(); return Promise.resolve();
} }
export function getParentNode(node: Node) {
// this also checks for host elements of shadow root node
// if the parent node is a document fragment (shadow root)
// then use the "host" property on it
// otherwise use the parent node
// DOCUMENT_FRAGMENT_NODE nodeType === 11
const parentNode: any = node.parentNode;
return (parentNode && parentNode.NODE_TYPE === 11 ? parentNode.host : parentNode);
}