Skip to content

Commit e628dbd

Browse files
authoredFeb 14, 2020
feat(ui5-file-uploader): initial implementation (#1184)
1 parent 78a9181 commit e628dbd

13 files changed

+761
-1
lines changed
 

‎packages/main/bundle.esm.js

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import ComboBox from "./dist/ComboBox.js";
3232
import ComboBoxItem from "./dist/ComboBoxItem.js";
3333
import DatePicker from "./dist/DatePicker.js";
3434
import Dialog from "./dist/Dialog.js";
35+
import FileUploader from "./dist/FileUploader.js";
3536
import Icon from "./dist/Icon.js";
3637
import Input from "./dist/Input.js";
3738
import Label from "./dist/Label.js";

‎packages/main/src/FileUploader.hbs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
<div class="ui5-file-uploader-root"
3+
@mouseover="{{_onmouseover}}"
4+
@mouseout="{{_onmouseout}}"
5+
>
6+
<div class="ui5-file-uploader-mask">
7+
{{#unless hideInput}}
8+
<ui5-input
9+
value="{{value}}"
10+
value-state="{{valueState}}"
11+
placeholder="{{placeholder}}"
12+
?disabled="{{disabled}}"
13+
></ui5-input>
14+
{{/unless}}
15+
<slot></slot>
16+
</div>
17+
{{#if _keepInputInShadowDOM}}
18+
<input
19+
type="file"
20+
title="upload file"
21+
accept="{{accept}}"
22+
?multiple="{{multiple}}"
23+
?disabled="{{disabled}}"
24+
@change="{{_onChange}}"
25+
>
26+
{{else}}
27+
<slot name="formSupport">
28+
{{!-- input for forms will be placed here on IE, Edge and Firefox --}}
29+
</slot>
30+
{{/if}}
31+
</div>

‎packages/main/src/FileUploader.js

+318
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
2+
import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js";
3+
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
4+
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
5+
import {
6+
fetchI18nBundle,
7+
getI18nBundle,
8+
} from "@ui5/webcomponents-base/dist/i18nBundle.js";
9+
import {
10+
FILEUPLOAD_BROWSE,
11+
} from "./generated/i18n/i18n-defaults.js";
12+
import Input from "./Input.js";
13+
14+
// Template
15+
import FileUploaderTemplate from "./generated/templates/FileUploaderTemplate.lit.js";
16+
17+
// Styles
18+
import FileUploaderCss from "./generated/themes/FileUploader.css.js";
19+
20+
/**
21+
* @public
22+
*/
23+
const metadata = {
24+
tag: "ui5-file-uploader",
25+
properties: /** @lends sap.ui.webcomponents.main.FileUploader.prototype */ {
26+
/**
27+
* Comma-separated list of file types that the <code>ui5-file-uploader</code> should accept.
28+
* @type {string}
29+
* @public
30+
*/
31+
accept: {
32+
type: String,
33+
},
34+
35+
/**
36+
* If set to "true", the input field of <code>ui5-file-uploader</code> will not be rendered. Only the default slot that is passed will be rendered.
37+
* @type {boolean}
38+
* @public
39+
*/
40+
hideInput: {
41+
type: Boolean,
42+
},
43+
44+
/**
45+
* Defines whether <code>ui5-file-uploader</code> is in disabled state.
46+
* <br><br>
47+
* <b>Note:</b> A disabled <code>ui5-input</code> is completely noninteractive.
48+
*
49+
* @type {boolean}
50+
* @defaultvalue false
51+
* @public
52+
*/
53+
disabled: {
54+
type: Boolean,
55+
},
56+
57+
/**
58+
* Allows multiple files to be chosen.
59+
* @type {boolean}
60+
* @defaultvalue false
61+
* @public
62+
*/
63+
multiple: {
64+
type: Boolean,
65+
},
66+
67+
/**
68+
* Determines the name with which the <code>ui5-file-uploader</code> will be submitted in an HTML form.
69+
*
70+
* <b>Important:</b> For the <code>name</code> property to have effect, you must add the following import to your project:
71+
* <code>import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js";</code>
72+
*
73+
* <b>Note:</b> When set, a native <code>input</code> HTML element
74+
* will be created inside the <code>ui5-file-uploader</code> so that it can be submitted as
75+
* part of an HTML form. Do not use this property unless you need to submit a form.
76+
*
77+
* @type {string}
78+
* @defaultvalue ""
79+
* @public
80+
*/
81+
name: {
82+
type: String,
83+
},
84+
85+
/**
86+
* Defines a short hint intended to aid the user with data entry when the <code>ui5-file-uploader</code> has no value.
87+
* @type {string}
88+
* @defaultvalue ""
89+
* @public
90+
*/
91+
placeholder: {
92+
type: String,
93+
},
94+
95+
/**
96+
* Name/names of the file/files to upload.
97+
* @type {string}
98+
* @defaultvalue ""
99+
* @public
100+
*/
101+
value: {
102+
type: String,
103+
},
104+
105+
/**
106+
* Defines the value state of the <code>ui5-file-uploader</code>.
107+
* Available options are: <code>None</code>, <code>Success</code>, <code>Warning</code>, and <code>Error</code>.
108+
*
109+
* @type {string}
110+
* @defaultvalue "None"
111+
* @public
112+
*/
113+
valueState: {
114+
type: ValueState,
115+
defaultValue: ValueState.None,
116+
},
117+
},
118+
slots: /** @lends sap.ui.webcomponents.main.FileUploader.prototype */ {
119+
/**
120+
* By default the <code>ui5-file-uploader</code> contains a single input field. With this slot you can pass any content that you wish to add. See the samples for more information
121+
*
122+
* @type {HTMLElement[]}
123+
* @slot
124+
* @public
125+
*/
126+
"default": {
127+
propertyName: "content",
128+
type: HTMLElement,
129+
},
130+
},
131+
events: /** @lends sap.ui.webcomponents.main.FileUploader.prototype */ {
132+
/**
133+
* Event is fired when the value of the file path has been changed.
134+
* Note: Keep in mind that because of the HTML input element of type file, the event is also fired in Chrome browser when the Cancel button of the uploads window is pressed.
135+
*
136+
* @event
137+
* @param {FileList} files The current files.
138+
* @public
139+
*/
140+
change: {
141+
detail: {
142+
files: { type: FileList },
143+
},
144+
},
145+
},
146+
};
147+
148+
/**
149+
* @class
150+
*
151+
* <h3 class="comment-api-title">Overview</h3>
152+
*
153+
*
154+
* <h3>Usage</h3>
155+
*
156+
* For the <code>ui5-file-uploader</code>
157+
* <h3>ES6 Module Import</h3>
158+
*
159+
* <code>import @ui5/webcomponents/dist/FileUploader.js";</code>
160+
*
161+
* @constructor
162+
* @author SAP SE
163+
* @alias sap.ui.webcomponents.main.FileUploader
164+
* @extends UI5Element
165+
* @tagname ui5-file-uploader
166+
* @public
167+
*/
168+
class FileUploader extends UI5Element {
169+
static get formAssociated() {
170+
return true;
171+
}
172+
173+
static get metadata() {
174+
return metadata;
175+
}
176+
177+
static get render() {
178+
return litRender;
179+
}
180+
181+
static get styles() {
182+
return FileUploaderCss;
183+
}
184+
185+
static get template() {
186+
return FileUploaderTemplate;
187+
}
188+
189+
constructor() {
190+
super();
191+
if (this._canUseNativeFormSupport) {
192+
this._internals = this.attachInternals();
193+
}
194+
195+
this.i18nBundle = getI18nBundle("@ui5/webcomponents");
196+
}
197+
198+
_onmouseover() {
199+
this.content.forEach(item => {
200+
item.classList.add("ui5_hovered");
201+
});
202+
}
203+
204+
_onmouseout() {
205+
this.content.forEach(item => {
206+
item.classList.remove("ui5_hovered");
207+
});
208+
}
209+
210+
/**
211+
* FileList of all selected files.
212+
* @readonly
213+
* @type { FileList }
214+
* @public
215+
*/
216+
get files() {
217+
if (this._input) {
218+
return this._input.files;
219+
}
220+
221+
return FileUploader._emptyFilesList;
222+
}
223+
224+
onBeforeRendering() {
225+
this._enableFormSupport();
226+
}
227+
228+
_enableFormSupport() {
229+
const FormSupport = getFeature("FormSupport");
230+
231+
if (FormSupport) {
232+
if (this._canUseNativeFormSupport) {
233+
this._setFormValue();
234+
} else {
235+
FormSupport.syncNativeFileInput(
236+
this,
237+
(element, nativeInput) => {
238+
nativeInput.disabled = element.disabled;
239+
},
240+
this._onChange.bind(this)
241+
);
242+
}
243+
} else if (this.name) {
244+
console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js";`); // eslint-disable-line
245+
}
246+
}
247+
248+
_onChange(event) {
249+
this._updateValue(event.target.files);
250+
this.fireEvent("change", {
251+
files: event.target.files,
252+
});
253+
}
254+
255+
_updateValue(files) {
256+
this.value = Array.from(files).reduce((acc, currFile) => {
257+
return `${acc}"${currFile.name}" `;
258+
}, "");
259+
}
260+
261+
_setFormValue() {
262+
const formData = new FormData();
263+
264+
for (let i = 0; i < this.files.length; i++) {
265+
formData.append(this.name, this.files[i]);
266+
}
267+
268+
this._internals.setFormValue(formData);
269+
}
270+
271+
/**
272+
* in case when ui5-file-uploader is not placed in the DOM, return empty FileList, like native input would do
273+
* @private
274+
*/
275+
static get _emptyFilesList() {
276+
if (!this.emptyInput) {
277+
this.emptyInput = document.createElement("input");
278+
this.emptyInput.type = "file";
279+
}
280+
return this.emptyInput.files;
281+
}
282+
283+
get browseText() {
284+
return this.i18nBundle.getText(FILEUPLOAD_BROWSE);
285+
}
286+
287+
get _canUseNativeFormSupport() {
288+
return !!this.attachInternals;
289+
}
290+
291+
get _keepInputInShadowDOM() {
292+
// only put input in the light dom when ui5-file-uploader is placed inside form and there is no support for form elements
293+
return this._canUseNativeFormSupport || !this.name;
294+
}
295+
296+
get _input() {
297+
return this.shadowRoot.querySelector("input[type=file]") || this.querySelector("input[type=file][data-ui5-form-support]");
298+
}
299+
300+
/**
301+
* Determines input helper type in forms.
302+
* @private
303+
*/
304+
get _type() {
305+
return "file";
306+
}
307+
308+
static async onDefine() {
309+
await Promise.all([
310+
Input.define(),
311+
fetchI18nBundle("@ui5/webcomponents"),
312+
]);
313+
}
314+
}
315+
316+
FileUploader.define();
317+
318+
export default FileUploader;

‎packages/main/src/features/InputElementsFormSupport.js

+35
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,41 @@ class FormSupport {
2626
}
2727
}
2828

29+
static syncNativeFileInput(element, nativeInputUpdateCallback, nativeInputChangeCallback) {
30+
const needsNativeInput = !!element.name;
31+
let nativeInput = element.querySelector(`input[type=${element._type || "hidden"}][data-ui5-form-support]`);
32+
33+
if (needsNativeInput && !nativeInput) {
34+
nativeInput = document.createElement("input");
35+
nativeInput.type = element._type;
36+
nativeInput.setAttribute("data-ui5-form-support", "");
37+
nativeInput.slot = "formSupport"; // Needed to visualize the input in the light dom
38+
nativeInput.style.position = "absolute";
39+
nativeInput.style.top = "0";
40+
nativeInput.style.left = "0";
41+
nativeInput.style.width = "100%";
42+
nativeInput.style.height = "100%";
43+
nativeInput.style.opacity = "0";
44+
45+
if (element.multiple) {
46+
nativeInput.multiple = true;
47+
}
48+
49+
nativeInput.addEventListener("change", nativeInputChangeCallback);
50+
51+
element.appendChild(nativeInput);
52+
}
53+
54+
if (!needsNativeInput && nativeInput) {
55+
element.removeChild(nativeInput);
56+
}
57+
58+
if (needsNativeInput) {
59+
nativeInput.name = element.name;
60+
(nativeInputUpdateCallback || copyDefaultProperties)(element, nativeInput);
61+
}
62+
}
63+
2964
static triggerFormSubmit(element) {
3065
if (!element.submits) {
3166
return;

‎packages/main/src/i18n/messagebundle.properties

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ CAROUSEL_OF_TEXT=of
4040
#XACT: DatePicker 'Open Picker' icon title
4141
DATEPICKER_OPEN_ICON_TITLE=Open Picker
4242

43+
FILEUPLOAD_BROWSE=Browse...
44+
4345
#XTXT
4446
ICON_ACTION_SETTINGS=Settings
4547

‎packages/main/src/themes/Avatar.css

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
box-sizing: border-box;
44
}
55

6+
:host(:not([hidden]).ui5_hovered) {
7+
opacity: .7;
8+
}
9+
610
:host {
711
height: 3rem;
812
width: 3rem;

‎packages/main/src/themes/Button.css

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
text-overflow: inherit;
5656
}
5757

58-
:host(:not([active]):hover) {
58+
:host(:not([active]):hover),
59+
:host(:not([hidden]).ui5_hovered) {
5960
background: var(--sapButton_Hover_Background);
6061
}
6162

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
:host {
2+
display: inline-block;
3+
}
4+
5+
.ui5-file-uploader-root {
6+
position: relative;
7+
}
8+
9+
.ui5-file-uploader-root input[type=file] {
10+
opacity: 0;
11+
position: absolute;
12+
top: 0;
13+
left: 0;
14+
height: 100%;
15+
width: 100%;
16+
}
17+
18+
.ui5-file-uploader-root input[type=file]:not([disabled]) {
19+
cursor: pointer;
20+
}
21+
22+
.ui5-file-uploader-mask {
23+
display: flex;
24+
}
25+
26+
.ui5-file-uploader-mask ui5-input {
27+
margin-right: 0.25rem;
28+
}
29+
30+
:host(:not([value-state]):not([disabled]):hover) ui5-input {
31+
background-color: var(--sapField_Hover_Background);
32+
border: 1px solid var(--sapField_Hover_BorderColor);
33+
}
34+
35+
:host(:not([disabled]):active) ui5-button {
36+
background-color: var(--sapButton_Active_Background);
37+
border-color: var(--_ui5_button_active_border_color);
38+
color: var(--sapButton_Active_TextColor);
39+
text-shadow: none;
40+
}

‎packages/main/src/themes/Icon.css

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
display: inline-block;
33
}
44

5+
:host(:not([hidden]).ui5_hovered) {
6+
opacity: .7;
7+
}
8+
59
:host {
610
width: 1rem;
711
height: 1rem;
+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7+
<title>FileUploader test page</title>
8+
9+
<script src="../../webcomponentsjs/webcomponents-loader.js"></script>
10+
<script src="../../resources/bundle.esm.js" type="module"></script>
11+
<script nomodule src="../../resources/bundle.es5.js"></script>
12+
<style>
13+
body > div {
14+
margin-bottom: 1rem;
15+
}
16+
</style>
17+
<script>
18+
delete Document.prototype.adoptedStyleSheets
19+
</script>
20+
</head>
21+
<body>
22+
<div>
23+
<label>Single file upload:</label>
24+
<ui5-file-uploader placeholder="upload file">
25+
<ui5-button>Upload</ui5-button>
26+
</ui5-file-uploader>
27+
</div>
28+
<div>
29+
<label>Multiple files upload:</label>
30+
<ui5-file-uploader multiple>
31+
<ui5-button>Upload</ui5-button>
32+
</ui5-file-uploader>
33+
</div>
34+
<div>
35+
<label>Accept only .txt and .docx files:</label>
36+
<ui5-file-uploader accept=".txt,.docx" id="file-uploader-accept">
37+
<ui5-button>Upload</ui5-button>
38+
</ui5-file-uploader>
39+
</div>
40+
<div>
41+
<label>Value state Error:</label>
42+
<ui5-file-uploader value-state="Error">
43+
<ui5-button icon="upload" icon-end>Upload</ui5-button>
44+
</ui5-file-uploader>
45+
</div>
46+
<div>
47+
<label>Disabled uploader:</label>
48+
<ui5-file-uploader disabled id="disabled"></ui5-file-uploader>
49+
</div>
50+
<div>
51+
<label>Button only:</label>
52+
<ui5-file-uploader hide-input id="file-uploader-no-input">
53+
<ui5-button icon="upload" icon-end>Upload</ui5-button>
54+
</ui5-file-uploader>
55+
</div>
56+
<div>
57+
<label>With Avatar:</label>
58+
<ui5-file-uploader hide-input>
59+
<ui5-avatar icon="upload"></ui5-avatar>
60+
</ui5-file-uploader>
61+
</div>
62+
<div>
63+
<label>With Icons:</label>
64+
<ui5-file-uploader hide-input>
65+
<ui5-icon name="upload"></ui5-icon>
66+
<ui5-icon name="upload"></ui5-icon>
67+
</ui5-file-uploader>
68+
</div>
69+
<div>
70+
<label>With badge:</label>
71+
<ui5-file-uploader hide-input>
72+
<ui5-badge>Upload File</ui5-badge>
73+
</ui5-file-uploader>
74+
</div>
75+
<div>
76+
<ui5-title>Form support</ui5-title>
77+
<form
78+
style="border: 1px solid black; padding: 1rem;"
79+
method="POST"
80+
action="http://localhost:3000/echo"
81+
enctype="multipart/form-data"
82+
>
83+
<div>
84+
<label>Disabled uploader:</label>
85+
<ui5-file-uploader disabled name="disabledUploader"></ui5-file-uploader>
86+
</div>
87+
<div>
88+
<label>Normal uploader:</label>
89+
<ui5-file-uploader name="enabledUploader"></ui5-file-uploader>
90+
</div>
91+
<div>
92+
<label>Native input type="file":</label>
93+
<input name="nativeInput" type="file">
94+
</div>
95+
<ui5-button submits>Submit</ui5-button>
96+
</form>
97+
</div>
98+
<div>
99+
<ui5-title>Upload files async using fetch</ui5-title>
100+
<div style="border: 1px solid black; padding: 1rem;">
101+
<ui5-file-uploader id="fuFetch"></ui5-file-uploader>
102+
<ui5-button id="uploadBtn">Upload</ui5-button>
103+
</div>
104+
</div>
105+
<script>
106+
document.getElementById("uploadBtn").addEventListener("click", () => {
107+
const fu = document.getElementById("fuFetch");
108+
const data = new FormData();
109+
110+
for (let i = 0; i < fu.files.length; i++) {
111+
data.append("file", fu.files[i]);
112+
}
113+
114+
fetch("http://localhost:3000/echo", {
115+
method: "POST",
116+
body: data
117+
})
118+
.then(res => {
119+
console.log(`Success! Response status: ${res.status}`);
120+
})
121+
.catch(err => {
122+
console.log("Error")
123+
})
124+
});
125+
</script>
126+
</body>
127+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<style>
2+
#result {
3+
width: 100%;
4+
display: flex;
5+
align-items: center;
6+
}
7+
#result > img {
8+
margin-right: 1rem;
9+
border-radius: .5rem;
10+
}
11+
</style>
12+
<header>
13+
<div class="control-header">File Uploader</div>
14+
</header>
15+
16+
<div class="component-package">@ui5/webcomponents</div>
17+
18+
<div class="control-tag">&lt;ui5-file-uploader&gt;</div>
19+
20+
<section>
21+
<h3>Upload multiple images</h3>
22+
<div class="snippet">
23+
<ui5-file-uploader id="fileuploader1" accept="image/*" multiple="true">
24+
<ui5-button icon="upload">Upload Images</ui5-button>
25+
</ui5-file-uploader>
26+
<div id="result"></div>
27+
<script>
28+
var fileUploader = document.querySelector("#fileuploader1"),
29+
resultDiv = document.querySelector("#result");
30+
fileUploader.addEventListener("change", function(event) {
31+
var files = event.target.files;
32+
33+
if (!files.length) {
34+
resultDiv.innerHTML = "<ui5-label>No Files Selected</ui5-label>";
35+
} else {
36+
resultDiv.innerHTML = "";
37+
resultDiv.style.marginTop = "1rem";
38+
39+
for (var i = 0; i < files.length; i++) {
40+
var img = document.createElement("img");
41+
img.src = URL.createObjectURL(files[i]);
42+
img.width = 100;
43+
img.height = 100;
44+
img.onload = function() {
45+
URL.revokeObjectURL(img.src);
46+
}
47+
resultDiv.appendChild(img);
48+
}
49+
}
50+
})
51+
</script>
52+
</div>
53+
<pre class="prettyprint lang-html"><xmp>
54+
<ui5-file-uploader id="fileuploader1" accept="image/*" multiple="true">
55+
<ui5-button icon="upload">Upload Images</ui5-button>
56+
</ui5-file-uploader>
57+
<script>
58+
const fileUploader = document.querySelector("#fileuploader1"),
59+
resultDiv = document.querySelector("#result");
60+
fileUploader.addEventListener("change", event => {
61+
const files = event.target.files;
62+
63+
if (!files.length) {
64+
resultDiv.innerHTML = "<ui5-label>No Files Selected</ui5-label>";
65+
} else {
66+
resultDiv.innerHTML = "";
67+
68+
for (let i = 0; i < files.length; i++) {
69+
const img = document.createElement("img");
70+
img.src = URL.createObjectURL(files[i]);
71+
img.width = 100;
72+
img.height = 100;
73+
img.onload = () => {
74+
URL.revokeObjectURL(img.src);
75+
}
76+
resultDiv.appendChild(img);
77+
}
78+
}
79+
})
80+
</script>
81+
</xmp></pre>
82+
</section>
83+
84+
<section>
85+
<h3>Upload Single File</h3>
86+
<div class="snippet">
87+
<ui5-file-uploader>
88+
<ui5-button>Upload Single File</ui5-button>
89+
</ui5-file-uploader>
90+
</div>
91+
<pre class="prettyprint lang-html"><xmp>
92+
<ui5-file-uploader>
93+
<ui5-button>Upload Single File</ui5-button>
94+
</ui5-file-uploader>
95+
</xmp></pre>
96+
</section>
97+
98+
<section>
99+
<h3>File Uploader With No Input</h3>
100+
<div class="snippet">
101+
<ui5-file-uploader hide-input>
102+
<ui5-button>Upload File</ui5-button>
103+
</ui5-file-uploader>
104+
</div>
105+
<pre class="prettyprint lang-html"><xmp>
106+
<ui5-file-uploader hide-input>
107+
<ui5-button>Upload File</ui5-button>
108+
</ui5-file-uploader>
109+
</xmp></pre>
110+
</section>
111+
112+
<section>
113+
<h3>Custom File Uploaders</h3>
114+
<div class="snippet">
115+
<ui5-file-uploader hide-input>
116+
<ui5-avatar icon="upload"></ui5-avatar>
117+
</ui5-file-uploader>
118+
119+
<ui5-file-uploader hide-input>
120+
<ui5-badge>Upload File</ui5-badge>
121+
</ui5-file-uploader>
122+
</div>
123+
<pre class="prettyprint lang-html"><xmp>
124+
<ui5-file-uploader hide-input>
125+
<ui5-avatar icon="upload"></ui5-avatar>
126+
</ui5-file-uploader>
127+
128+
<ui5-file-uploader hide-input>
129+
<ui5-badge>Upload File</ui5-badge>
130+
</ui5-file-uploader>
131+
</xmp></pre>
132+
</section>
133+
134+
<section>
135+
<h3>Button With Icon File Uploader</h3>
136+
<div class="snippet">
137+
<ui5-file-uploader>
138+
<ui5-button icon="upload">Upload</ui5-button>
139+
</ui5-file-uploader>
140+
<ui5-file-uploader>
141+
<ui5-button icon="upload" icon-end>Upload</ui5-button>
142+
</ui5-file-uploader>
143+
<ui5-file-uploader>
144+
<ui5-button icon="upload" icon-only></ui5-button>
145+
</ui5-file-uploader>
146+
</div>
147+
<pre class="prettyprint lang-html"><xmp>
148+
<ui5-file-uploader>
149+
<ui5-button icon="upload">Upload</ui5-button>
150+
</ui5-file-uploader>
151+
<ui5-file-uploader>
152+
<ui5-button icon="upload" icon-end>Upload</ui5-button>
153+
</ui5-file-uploader>
154+
<ui5-file-uploader>
155+
<ui5-button icon="upload" icon-only></ui5-button>
156+
</ui5-file-uploader>
157+
</xmp></pre>
158+
</section>
159+
160+
161+
162+
<!-- JSDoc marker -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const assert = require("chai").assert;
2+
3+
describe("API", () => {
4+
browser.url("http://localhost:8080/test-resources/pages/FileUploader.html");
5+
6+
it("Files property", () => {
7+
const fileUploader = $("ui5-file-uploader");
8+
assert.ok(fileUploader.getProperty("files"), "Property 'files' should return FileList with 0 files.")
9+
});
10+
11+
it("File upload with no input", () => {
12+
const fileUploader = $("#file-uploader-no-input");
13+
const inputField = fileUploader.shadow$("ui5-input");
14+
assert.notOk(inputField.isExisting(), "Input should not be rendered.");
15+
});
16+
17+
it("Default slot is working", () => {
18+
const fileUploader = $("#file-uploader-no-input");
19+
const button = fileUploader.shadow$("ui5-button");
20+
assert.notOk(button.isExisting(), "Button should be rendered.");
21+
});
22+
23+
it("Tests disabled file uploader", () => {
24+
const fileUploader = $("#disabled");
25+
const input = fileUploader.shadow$("input");
26+
assert.ok(input.getProperty("disabled"), "Native input is disabled.");
27+
});
28+
29+
it("Tests accept property", () => {
30+
const fileUploader = $("#file-uploader-accept");
31+
const input = fileUploader.shadow$("input");
32+
assert.strictEqual(input.getProperty("accept"), ".txt,.docx", "Native input is has the rignt accept property.");
33+
});
34+
});

‎packages/playground/build-scripts/samples-prepare.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const newComponents = [
1515
"Avatar",
1616
"Carousel",
1717
"ComboBox",
18+
"FileUploader",
1819
"ResponsivePopover",
1920
"SegmentedButton",
2021
"Toast",

0 commit comments

Comments
 (0)
Please sign in to comment.