mirror of
https://github.com/Hopiu/vue-material.git
synced 2026-04-27 18:14:48 +00:00
create file input #259
This commit is contained in:
parent
42cf0eb7fe
commit
a359301940
6 changed files with 240 additions and 37 deletions
|
|
@ -2,7 +2,7 @@
|
|||
<page-content page-title="Components - File">
|
||||
<docs-component>
|
||||
<div slot="description">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam debitis consequatur placeat! Velit, esse alias voluptatem dolor facere cumque placeat at similique consequatur, minima assumenda eaque quis laborum. Quia, deleniti.</p>
|
||||
<p>The file picker aim to select files like images, videos and other formats. They can have multiselection and use the devide file system to pick the file.</p>
|
||||
</div>
|
||||
|
||||
<div slot="api">
|
||||
|
|
@ -18,9 +18,45 @@
|
|||
|
||||
<md-table-body>
|
||||
<md-table-row>
|
||||
<md-table-cell>empty</md-table-cell>
|
||||
<md-table-cell><code>Type</code></md-table-cell>
|
||||
<md-table-cell>Description</md-table-cell>
|
||||
<md-table-cell>v-model</md-table-cell>
|
||||
<md-table-cell><code>String</code></md-table-cell>
|
||||
<md-table-cell>A required model object to bind the value.</md-table-cell>
|
||||
</md-table-row>
|
||||
|
||||
<md-table-row>
|
||||
<md-table-cell>id</md-table-cell>
|
||||
<md-table-cell><code>String</code></md-table-cell>
|
||||
<md-table-cell>Sets the input id.</md-table-cell>
|
||||
</md-table-row>
|
||||
|
||||
<md-table-row>
|
||||
<md-table-cell>name</md-table-cell>
|
||||
<md-table-cell><code>String</code></md-table-cell>
|
||||
<md-table-cell>Sets the input name.</md-table-cell>
|
||||
</md-table-row>
|
||||
|
||||
<md-table-row>
|
||||
<md-table-cell>disabled</md-table-cell>
|
||||
<md-table-cell><code>Boolean</code></md-table-cell>
|
||||
<md-table-cell>Disable the input and prevent his actions. Default <code>false</code></md-table-cell>
|
||||
</md-table-row>
|
||||
|
||||
<md-table-row>
|
||||
<md-table-cell>required</md-table-cell>
|
||||
<md-table-cell><code>Boolean</code></md-table-cell>
|
||||
<md-table-cell>Apply the required rule to style the label with an "*". Default <code>false</code></md-table-cell>
|
||||
</md-table-row>
|
||||
|
||||
<md-table-row>
|
||||
<md-table-cell>accept</md-table-cell>
|
||||
<md-table-cell><code>String</code></md-table-cell>
|
||||
<md-table-cell>Filter files that can be selected by mimetype pattern.</md-table-cell>
|
||||
</md-table-row>
|
||||
|
||||
<md-table-row>
|
||||
<md-table-cell>multiple</md-table-cell>
|
||||
<md-table-cell><code>Boolean</code></md-table-cell>
|
||||
<md-table-cell>Enable multiple selection.</md-table-cell>
|
||||
</md-table-row>
|
||||
</md-table-body>
|
||||
</md-table>
|
||||
|
|
@ -28,10 +64,34 @@
|
|||
</div>
|
||||
|
||||
<div slot="example">
|
||||
<example-box card-title="Default">
|
||||
<example-box card-title="Single File">
|
||||
<div slot="demo">
|
||||
<md-input-container>
|
||||
<md-file></md-file>
|
||||
<label>Single</label>
|
||||
<md-file v-model="single"></md-file>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<md-file v-model="placeholder" placeholder="A nice input placeholder"></md-file>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<md-file placeholder="Disabled" disabled></md-file>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label>Initial Value</label>
|
||||
<md-file v-model="initialValue"></md-file>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label>Multiple</label>
|
||||
<md-file v-model="multiple" multiple></md-file>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label>Only Images</label>
|
||||
<md-file v-model="onlyImages" accept="image/*"></md-file>
|
||||
</md-input-container>
|
||||
</div>
|
||||
|
||||
|
|
@ -49,7 +109,11 @@
|
|||
<script>
|
||||
export default {
|
||||
data: () => ({
|
||||
|
||||
single: null,
|
||||
placeholder: null,
|
||||
initialValue: 'my-profile-picture.jpg',
|
||||
multiple: null,
|
||||
onlyImages: null
|
||||
}),
|
||||
methods: {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
@import '../../core/stylesheets/variables.scss';
|
||||
|
||||
.md-file {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
input[type="file"] {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
clip: rect(0 0 0 0);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.md-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +1,100 @@
|
|||
<template>
|
||||
<div class="md-file" :class="[themeClass, classes]">
|
||||
<slot></slot>
|
||||
<div class="md-file" @click="openPicker">
|
||||
<md-input
|
||||
readonly
|
||||
v-model="filename"
|
||||
:required="required"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
ref="textInput">
|
||||
</md-input>
|
||||
|
||||
<md-icon>attach_file</md-icon>
|
||||
|
||||
<input
|
||||
type="file"
|
||||
:id="id"
|
||||
:name="name"
|
||||
:disabled="disabled"
|
||||
:multiple="multiple"
|
||||
:accept="accept"
|
||||
@change="onFileSelected"
|
||||
ref="fileInput">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" src="./mdFile.scss"></style>
|
||||
|
||||
<script>
|
||||
import theme from '../../core/components/mdTheme/mixin';
|
||||
import getClosestVueParent from '../../core/utils/getClosestVueParent';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
||||
value: String,
|
||||
id: String,
|
||||
name: String,
|
||||
disabled: Boolean,
|
||||
required: Boolean,
|
||||
placeholder: String,
|
||||
accept: String,
|
||||
multiple: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
filename: this.value
|
||||
};
|
||||
},
|
||||
mixins: [theme],
|
||||
data: () => ({
|
||||
|
||||
}),
|
||||
watch: {
|
||||
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
|
||||
};
|
||||
value() {
|
||||
this.filename = this.value;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getMultipleName(files) {
|
||||
let names = [];
|
||||
|
||||
[...files].forEach((file) => {
|
||||
names.push(file.name);
|
||||
});
|
||||
|
||||
return names.join(', ');
|
||||
},
|
||||
openPicker() {
|
||||
if (!this.disabled) {
|
||||
this.$refs.fileInput.click();
|
||||
this.$refs.textInput.$el.focus();
|
||||
}
|
||||
},
|
||||
onFileSelected($event) {
|
||||
const files = $event.target.files || $event.dataTransfer.files;
|
||||
|
||||
if (files) {
|
||||
if (files.length > 1) {
|
||||
this.filename = this.getMultipleName(files);
|
||||
} else if (files.length === 1) {
|
||||
this.filename = files[0].name;
|
||||
}
|
||||
} else {
|
||||
this.filename = $event.target.value.split('\\').pop();
|
||||
}
|
||||
|
||||
this.$emit('selected', files || $event.target.value);
|
||||
this.$emit('input', this.filename);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
mounted() {
|
||||
this.parentContainer = getClosestVueParent(this.$parent, 'md-input-container');
|
||||
|
||||
if (!this.parentContainer) {
|
||||
this.$destroy();
|
||||
|
||||
throw new Error('You should wrap the md-file in a md-input-container');
|
||||
}
|
||||
|
||||
this.parentContainer.hasFile = true;
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.parentContainer.hasFile = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ $input-size: 32px;
|
|||
min-height: 48px;
|
||||
margin: 4px 0 24px;
|
||||
padding-top: 16px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
|
|
@ -38,6 +39,7 @@ $input-size: 32px;
|
|||
height: $input-size;
|
||||
padding: 0;
|
||||
display: block;
|
||||
flex: 1;
|
||||
border: none;
|
||||
background: none;
|
||||
transition: $swift-ease-out;
|
||||
|
|
@ -57,6 +59,15 @@ $input-size: 32px;
|
|||
text-shadow: none;
|
||||
-webkit-text-fill-color: initial;
|
||||
}
|
||||
|
||||
~ .md-icon {
|
||||
margin-left: 12px;
|
||||
|
||||
&:after {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
|
|
@ -67,22 +78,51 @@ $input-size: 32px;
|
|||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
.md-error {
|
||||
height: 20px;
|
||||
display: block !important;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -8px, 0);
|
||||
transition: $swift-ease-in;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.md-error,
|
||||
.md-count {
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.md-error {
|
||||
display: block !important;
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -8px, 0);
|
||||
transition: $swift-ease-in;
|
||||
}
|
||||
|
||||
.md-count {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.md-icon {
|
||||
color: rgba(#000, .54);
|
||||
transition: $swift-ease-out;
|
||||
|
||||
&:after {
|
||||
width: 36px;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 2;
|
||||
content: "";
|
||||
}
|
||||
|
||||
~ {
|
||||
label {
|
||||
left: 36px;
|
||||
}
|
||||
|
||||
.md-input,
|
||||
.md-textarea,
|
||||
.md-file {
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.md-input-container {
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@
|
|||
}
|
||||
|
||||
label,
|
||||
input,
|
||||
textarea,
|
||||
.md-error,
|
||||
.md-count,
|
||||
input,
|
||||
textarea {
|
||||
.md-icon {
|
||||
color: #{'WARN-COLOR'};
|
||||
}
|
||||
}
|
||||
|
|
@ -39,9 +40,26 @@
|
|||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
label {
|
||||
label,
|
||||
.md-icon {
|
||||
color: #{'PRIMARY-COLOR'};
|
||||
}
|
||||
}
|
||||
|
||||
&.md-input-disabled {
|
||||
label,
|
||||
input,
|
||||
textarea,
|
||||
.md-error,
|
||||
.md-count,
|
||||
.md-icon,
|
||||
::-webkit-input-placeholder {
|
||||
color: #{'BACKGROUND-CONTRAST-0.38'};
|
||||
}
|
||||
}
|
||||
|
||||
.md-icon:after {
|
||||
background: #{'BACKGROUND-COLOR'};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
enableCounter: false,
|
||||
hasSelect: false,
|
||||
hasPlaceholder: false,
|
||||
hasFile: false,
|
||||
isDisabled: false,
|
||||
isRequired: false,
|
||||
isFocused: false,
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
'md-input-inline': this.mdInline,
|
||||
'md-has-password': this.mdHasPassword,
|
||||
'md-has-select': this.hasSelect,
|
||||
'md-has-file': this.hasFile,
|
||||
'md-has-value': this.hasValue,
|
||||
'md-input-placeholder': this.hasPlaceholder,
|
||||
'md-input-disabled': this.isDisabled,
|
||||
|
|
|
|||
Loading…
Reference in a new issue