mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-03-01 13:36:55 +08:00
Merge branch 'develop' of ***REMOVED*** into develop
This commit is contained in:
commit
9da46498ab
@ -24,7 +24,7 @@ Run `npm run test` to test all components.
|
||||
Run `npm run test-cov` to test all components and see detailed test coverage report.
|
||||
|
||||
## Want to see how component works
|
||||
1. Run `npm run build`
|
||||
1. Run `npm run dev`
|
||||
2. Open `http://localhost:8086/` in browser.
|
||||
## Want to add your own component
|
||||
There is no guideline for now. If you want to know how to do it, you can explore by yourself or ask `lecong.zhang@tusimple.ai`.
|
||||
|
908
demo/components/formDemo.vue
Normal file
908
demo/components/formDemo.vue
Normal file
@ -0,0 +1,908 @@
|
||||
<template>
|
||||
<div
|
||||
ref="doc"
|
||||
class="n-doc"
|
||||
>
|
||||
<div class="n-doc-header">
|
||||
<n-gradient-text :font-size="20">
|
||||
Form / n-form
|
||||
</n-gradient-text>
|
||||
</div>
|
||||
<div class="n-doc-body">
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Inline Form
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
<n-form
|
||||
inline
|
||||
:label-width="80"
|
||||
>
|
||||
<n-form-item label="name">
|
||||
<n-input placeholder="Input your name" />
|
||||
</n-form-item>
|
||||
<n-form-item label="age">
|
||||
<n-input placeholder="Input your age" />
|
||||
</n-form-item>
|
||||
<n-form-item label="phone">
|
||||
<n-input placeholder="Input your phone number" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea>
|
||||
<n-form inline
|
||||
:label-width="80">
|
||||
<n-form-item :model="form" label="name">
|
||||
<n-input v-model="form.name" placeholder="Input your name" />
|
||||
</n-form-item>
|
||||
<n-form-item label="age">
|
||||
<n-input v-model="form.age" placeholder="Input your age" />
|
||||
</n-form-item>
|
||||
<n-form-item label="phone">
|
||||
<n-input v-model="form.phone" placeholder="Input your phone number" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
age: '',
|
||||
phone: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Form Item
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
<n-form :model="form">
|
||||
<n-form-item label="Input">
|
||||
<n-input
|
||||
v-model="form.input"
|
||||
placeholder="Enter sth"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Select">
|
||||
<n-select
|
||||
v-model="form.select"
|
||||
size="small"
|
||||
placeholder="Please Select Type"
|
||||
:items="items"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Switch">
|
||||
<n-switch v-model="form.switch" />
|
||||
</n-form-item>
|
||||
<n-form-item label="DatePicker">
|
||||
<n-date-picker
|
||||
v-model="form.dateTimeTimestamp"
|
||||
type="datetime"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Switch">
|
||||
<n-radio
|
||||
v-model="form.radio"
|
||||
value="Definitely Maybe"
|
||||
>
|
||||
Definitely Maybe
|
||||
</n-radio>
|
||||
<n-radio
|
||||
v-model="form.radio"
|
||||
value="Be Here Now"
|
||||
>
|
||||
Be Here Now
|
||||
</n-radio>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button>Submit</n-button>
|
||||
<n-button>Cancel</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea>
|
||||
<n-form :model="form">
|
||||
<n-form-item label="Input">
|
||||
<n-input v-model="form.input" placeholder="Enter sth" />
|
||||
</n-form-item>
|
||||
<n-form-item label="Select">
|
||||
<n-select size="small" v-model="form.select"
|
||||
placeholder="Please Select Type" :items="items" />
|
||||
</n-form-item>
|
||||
<n-form-item label="Switch">
|
||||
<n-switch v-model="form.switch" />
|
||||
</n-form-item>
|
||||
<n-form-item label="DatePicker">
|
||||
<n-date-picker v-model="form.dateTimeTimestamp"
|
||||
type="datetime" />
|
||||
</n-form-item>
|
||||
<n-form-item label="Switch">
|
||||
<n-radio v-model="form.radio" value="Definitely Maybe">
|
||||
Definitely Maybe</n-radio>
|
||||
<n-radio v-model="form.radio" value="Be Here Now">
|
||||
Be Here Now</n-radio>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button>Submit</n-button>
|
||||
<n-button>Cancel</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
items: [
|
||||
{
|
||||
label: "ArtifactoryLabel",
|
||||
value: "Artifactory"
|
||||
},
|
||||
{
|
||||
label: "Registry",
|
||||
value: "Registry"
|
||||
},
|
||||
{
|
||||
label: "Public",
|
||||
value: "Public"
|
||||
},
|
||||
{
|
||||
label: "Custom",
|
||||
value: "Custom"
|
||||
}
|
||||
],
|
||||
form: {
|
||||
input: '',
|
||||
select: '',
|
||||
datepicker: 0,
|
||||
switch: false,
|
||||
radio: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Form of Label Position
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
<n-form
|
||||
:label-width="200"
|
||||
label-position="top"
|
||||
>
|
||||
<n-form-item label="Top1">
|
||||
<n-input />
|
||||
</n-form-item>
|
||||
<n-form-item label="Top2">
|
||||
<n-input />
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label-position="left"
|
||||
label="Left"
|
||||
>
|
||||
<n-input />
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label-position="center"
|
||||
label="Center"
|
||||
>
|
||||
<n-input />
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label-position="right"
|
||||
label="Right"
|
||||
>
|
||||
<n-input />
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button>Submit</n-button>
|
||||
<n-button>Cancel</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="Action"
|
||||
label-position="right"
|
||||
>
|
||||
<n-button>Submit</n-button>
|
||||
<n-button>Cancel</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea>
|
||||
<n-form
|
||||
:label-width="200"
|
||||
label-position="top"
|
||||
>
|
||||
<n-form-item label="Top1">
|
||||
<n-input/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Top2">
|
||||
<n-input/>
|
||||
</n-form-item>
|
||||
<n-form-item label-position="left" label="Left">
|
||||
<n-input/>
|
||||
</n-form-item>
|
||||
<n-form-item label-position="center" label="Center">
|
||||
<n-input/>
|
||||
</n-form-item>
|
||||
<n-form-item label-position="right" label="Right">
|
||||
<n-input/>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button>Submit</n-button>
|
||||
<n-button>Cancel</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item label="Action" label-position="right">
|
||||
<n-button>Submit</n-button>
|
||||
<n-button>Cancel</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Validate Form
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
<n-form
|
||||
ref="form-validate"
|
||||
:model="validateForm"
|
||||
:rules="validateRules"
|
||||
>
|
||||
<n-form-item
|
||||
label="Warning"
|
||||
label-position="top"
|
||||
>
|
||||
The key in form-model does not support the form with ' . '.<br>
|
||||
And does not init the value of parameters with 'undefined'.<br>
|
||||
ResetForm Method: only can reset the item with prop.<br>
|
||||
ValidateForm Method: support validate specified items by the second parameter in form of array.<br>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
:required-logo="false"
|
||||
prop="input"
|
||||
label="Input"
|
||||
>
|
||||
<n-input
|
||||
v-model="validateForm.input"
|
||||
placeholder="Enter string"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
prop="muti.deep.select"
|
||||
label="Select"
|
||||
>
|
||||
<n-select
|
||||
v-model="validateForm.muti.deep.select"
|
||||
placeholder="Please Select Type"
|
||||
:items="items"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="Switch"
|
||||
prop="switch"
|
||||
>
|
||||
<n-switch v-model="validateForm.switch" />
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="DatePicker"
|
||||
prop="datepicker"
|
||||
>
|
||||
<n-date-picker
|
||||
v-model="validateForm.datepicker"
|
||||
type="date"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
prop="radio"
|
||||
label="Radio"
|
||||
>
|
||||
<n-radio
|
||||
v-model="validateForm.radio"
|
||||
value="Definitely Maybe"
|
||||
>
|
||||
Definitely Maybe
|
||||
</n-radio>
|
||||
<n-radio
|
||||
v-model="validateForm.radio"
|
||||
value="Be Here Now"
|
||||
>
|
||||
Be Here Now
|
||||
</n-radio>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button @click="formValidate('form-validate')">
|
||||
Submit
|
||||
</n-button>
|
||||
<n-button @click="formReset('form-validate')">
|
||||
Reset
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea v-pre>
|
||||
<n-form ref="form-validate" disabled :model="validateForm" :rules="validateRules">
|
||||
<n-form-item prop="input" label="Input">
|
||||
<n-input v-model="validateForm.input" placeholder="Enter string" />
|
||||
</n-form-item>
|
||||
<n-form-item prop="muti.deep.select" label="Select">
|
||||
<n-select
|
||||
size="small"
|
||||
v-model="validateForm.muti.deep.select"
|
||||
placeholder="Please Select Type"
|
||||
:items="items"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Switch" prop="switch">
|
||||
<n-switch v-model="validateForm.switch" />
|
||||
</n-form-item>
|
||||
<n-form-item label="DatePicker" prop="datepicker">
|
||||
<n-date-picker v-model="validateForm.datepicker" type="date" />
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
prop="radio"
|
||||
label="Radio">
|
||||
<n-radio v-model="validateForm.radio" value="Definitely Maybe">
|
||||
Definitely Maybe
|
||||
</n-radio>
|
||||
<n-radio v-model="validateForm.radio" value="Be Here Now">
|
||||
Be Here Now
|
||||
</n-radio>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button @click="formValidate('form-validate')">
|
||||
Submit
|
||||
</n-button>
|
||||
<n-button @click="formReset('form-validate')">
|
||||
Reset
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
validateForm: {
|
||||
input: "",
|
||||
muti: {
|
||||
deep: {
|
||||
select: ""
|
||||
}
|
||||
},
|
||||
datepicker: "",
|
||||
switch: false,
|
||||
radio: ""
|
||||
},
|
||||
validateRules: {
|
||||
input: [
|
||||
{ required: true, message: "input cannot be empty", trigger: "blur" }
|
||||
],
|
||||
"muti.deep.select": [
|
||||
{
|
||||
required: true,
|
||||
message: "select cannot be empty",
|
||||
trigger: "change"
|
||||
}
|
||||
],
|
||||
radio: [
|
||||
{
|
||||
required: true,
|
||||
message: "radio please choose some",
|
||||
trigger: "change"
|
||||
}
|
||||
],
|
||||
datepicker: [
|
||||
{
|
||||
required: true,
|
||||
type: "date",
|
||||
message: "Please select the date",
|
||||
trigger: "change"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formValidate(ref) {
|
||||
// two ways to use, the first used most
|
||||
// this.$refs[ref].validate((flag, res) => {
|
||||
// console.log("validate all result", flag, res);
|
||||
// });
|
||||
new Promise((resolve, reject) => {
|
||||
this.$refs[ref].validate((valid, filed) => {
|
||||
if (valid) {
|
||||
resolve(filed);
|
||||
} else {
|
||||
reject(filed);
|
||||
}
|
||||
});
|
||||
})
|
||||
.then(f => {
|
||||
console.log("pass", f);
|
||||
})
|
||||
.catch(e => {
|
||||
console.log("unpass", e);
|
||||
});
|
||||
},
|
||||
formReset (ref) {
|
||||
this.$refs[ref].resetForm();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Form of Custom validate rules
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
<n-form
|
||||
ref="custom"
|
||||
:model="custom"
|
||||
:rules="customRules"
|
||||
:label-width="80"
|
||||
>
|
||||
<n-form-item
|
||||
prop="age"
|
||||
label="Age"
|
||||
>
|
||||
<n-input v-model.number="custom.age" />
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
prop="pass"
|
||||
label="Password"
|
||||
>
|
||||
<n-input
|
||||
v-model="custom.pass"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
prop="checkPass"
|
||||
label="CheckPass"
|
||||
>
|
||||
<n-input v-model="custom.checkPass" />
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button @click="formValidate('custom')">
|
||||
Commit
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea v-pre>
|
||||
<n-form ref="custom" :model="custom" :rules="customRules" :label-width="80">
|
||||
<n-form-item prop="age" label="Age">
|
||||
<n-input v-model.number="custom.age"></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item prop="pass" label="Password">
|
||||
<n-input v-model="custom.pass"></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item prop="checkPass" label="CheckPass">
|
||||
<n-input v-model="custom.checkPass"></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button @click="formValidate('custom')">Commit</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
var checkAge = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
return callback(new Error("Input age"));
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (!Number.isInteger(value)) {
|
||||
callback(new Error("Number required"));
|
||||
} else {
|
||||
if (value < 18) {
|
||||
callback(new Error("Age should over 18"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
var validatePass = (rule, value, callback) => {
|
||||
if (value === "") {
|
||||
callback(new Error("Input password"));
|
||||
} else {
|
||||
if (this.custom.checkPass !== "") {
|
||||
this.$refs.custom.validate("", ["checkPass"]);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
};
|
||||
var validatePass2 = (rule, value, callback) => {
|
||||
if (value === "") {
|
||||
callback(new Error("Input password again"));
|
||||
} else if (value !== this.custom.pass) {
|
||||
callback(new Error("ent input password twice!"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
custom: {
|
||||
pass: "",
|
||||
checkPass: "",
|
||||
age: ""
|
||||
},
|
||||
customRules: {
|
||||
pass: [{ validator: validatePass, trigger: "blur" }],
|
||||
checkPass: [{ validator: validatePass2, trigger: "blur" }],
|
||||
age: [{ validator: checkAge, trigger: "blur" }]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Form of Dynamic
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
<n-form
|
||||
ref="custom"
|
||||
:model="dynamic"
|
||||
:rules="dynamicRules"
|
||||
:label-width="80"
|
||||
>
|
||||
<n-form-item
|
||||
v-for="(item, k) in dynamic.email"
|
||||
:key="k"
|
||||
:prop="'email.' + k"
|
||||
:label="k"
|
||||
>
|
||||
<n-input v-model="dynamic['email'][k]" />
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button @click="dynamicAddItem">
|
||||
Add
|
||||
</n-button>
|
||||
<n-button @click="dynamicPopItem">
|
||||
Delete
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea v-pre>
|
||||
<n-form ref="dynamic" :model="dynamic" :rules="dynamicRules" :label-width="80">
|
||||
<n-form-item
|
||||
:key="k"
|
||||
:prop="'email.' + k"
|
||||
:label="k"
|
||||
v-for="(item, k) in dynamic.email"
|
||||
>
|
||||
<n-input v-model="dynamic['email'][k]"></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button @click="dynamicAddItem">Add item</n-button>
|
||||
<n-button @click="dynamicPopItem">Delete</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
dynamic: {
|
||||
name: "",
|
||||
email: {
|
||||
email0: ""
|
||||
}
|
||||
},
|
||||
dynamicRules: {
|
||||
"email.email0": [
|
||||
{
|
||||
required: true,
|
||||
message: "Mailbox cannot be empty",
|
||||
trigger: "blur"
|
||||
},
|
||||
{ type: "email", message: "Incorrect email format", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
dynamicAddItem() {
|
||||
let i = Object.keys(this.dynamic.email).length;
|
||||
this.$set(this.dynamic.email, "email" + i, "");
|
||||
// 依据自己的情况在dynamicRules里去增加验证对象
|
||||
this.$set(
|
||||
this.dynamicRules,
|
||||
"email.email" + i,
|
||||
this.dynamicRules["email.email0"]
|
||||
);
|
||||
},
|
||||
dynamicPopItem () {
|
||||
let keys = Object.keys(this.dynamic.email)
|
||||
let k = keys[keys.length - 1]
|
||||
if (k) {
|
||||
delete this.dynamic.email[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import docCodeEditorMixin from './docCodeEditorMixin'
|
||||
|
||||
export default {
|
||||
mixins: [docCodeEditorMixin],
|
||||
|
||||
data () {
|
||||
var checkAge = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
return callback(new Error('Input age'))
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (!Number.isInteger(value)) {
|
||||
callback(new Error('Number required'))
|
||||
} else {
|
||||
if (value < 18) {
|
||||
callback(new Error('Age should over 18'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
var validatePass = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('Input password'))
|
||||
} else {
|
||||
if (this.custom.checkPass !== '') {
|
||||
this.$refs.custom.validate('', ['checkPass'])
|
||||
}
|
||||
callback()
|
||||
}
|
||||
}
|
||||
var validatePass2 = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('Input password again'))
|
||||
} else if (value !== this.custom.pass) {
|
||||
callback(new Error('ent input password twice!'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
age: '',
|
||||
phone: '',
|
||||
// second form
|
||||
input: '',
|
||||
select: '',
|
||||
datepicker: '',
|
||||
switch: false,
|
||||
radio: ''
|
||||
},
|
||||
items: [
|
||||
{
|
||||
label: 'ArtifactoryLabel',
|
||||
value: 'Artifactory'
|
||||
},
|
||||
{
|
||||
label: 'Registry',
|
||||
value: 'Registry'
|
||||
},
|
||||
{
|
||||
label: 'Public',
|
||||
value: 'Public'
|
||||
},
|
||||
{
|
||||
label: 'Custom',
|
||||
value: 'Custom'
|
||||
}
|
||||
],
|
||||
validateForm: {
|
||||
input: 'input',
|
||||
muti: {
|
||||
deep: {
|
||||
select: 'Public'
|
||||
}
|
||||
},
|
||||
datepicker: 0,
|
||||
switch: false,
|
||||
radio: ''
|
||||
},
|
||||
validateRules: {
|
||||
input: [
|
||||
{ required: true, message: 'input cannot be empty', trigger: 'blur' }
|
||||
],
|
||||
'muti.deep.select': [
|
||||
{
|
||||
required: true,
|
||||
message: 'select cannot be empty',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
radio: [
|
||||
{
|
||||
required: true,
|
||||
message: 'radio please choose some',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
datepicker: [
|
||||
{
|
||||
required: true,
|
||||
type: 'date',
|
||||
message: 'Please select the date',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
},
|
||||
ruleValidate: {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: 'The name cannot be empty',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
mail: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Mailbox cannot be empty',
|
||||
trigger: 'blur'
|
||||
},
|
||||
{ type: 'email', message: 'Incorrect email format', trigger: 'blur' }
|
||||
],
|
||||
city: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please select the city',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
gender: [
|
||||
{ required: true, message: 'Please select gender', trigger: 'change' }
|
||||
],
|
||||
interest: [
|
||||
{
|
||||
required: true,
|
||||
type: 'array',
|
||||
min: 1,
|
||||
message: 'Choose at least one hobby',
|
||||
trigger: 'change'
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
max: 2,
|
||||
message: 'Choose two hobbies at best',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
date: [
|
||||
{
|
||||
required: true,
|
||||
type: 'date',
|
||||
message: 'Please select the date',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
time: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: 'Please select time',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
desc: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please enter a personal introduction',
|
||||
trigger: 'blur'
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
min: 20,
|
||||
message: 'Introduce no less than 20 words',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
},
|
||||
custom: {
|
||||
pass: '',
|
||||
checkPass: '',
|
||||
age: ''
|
||||
},
|
||||
customRules: {
|
||||
pass: [{ validator: validatePass, trigger: 'blur' }],
|
||||
checkPass: [{ validator: validatePass2, trigger: 'blur' }],
|
||||
age: [{ validator: checkAge, trigger: 'blur' }]
|
||||
},
|
||||
dynamic: {
|
||||
name: '',
|
||||
email: {
|
||||
email0: ''
|
||||
}
|
||||
},
|
||||
dynamicRules: {
|
||||
'email.email0': [
|
||||
{
|
||||
required: true,
|
||||
message: 'Mailbox cannot be empty',
|
||||
trigger: 'blur'
|
||||
},
|
||||
{ type: 'email', message: 'Incorrect email format', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
formValidate (ref) {
|
||||
// this.$refs[ref].validate((flag, res) => {
|
||||
// console.log('validate all result', flag, res);
|
||||
// })
|
||||
new Promise((resolve, reject) => {
|
||||
this.$refs[ref].validate((valid, filed) => {
|
||||
if (valid) {
|
||||
resolve(filed)
|
||||
} else {
|
||||
reject(filed)
|
||||
}
|
||||
})
|
||||
})
|
||||
.then(f => {
|
||||
console.log('pass', f)
|
||||
})
|
||||
.catch(e => {
|
||||
console.log('unpass', e)
|
||||
})
|
||||
},
|
||||
|
||||
formReset (ref) {
|
||||
this.$refs[ref].resetForm()
|
||||
},
|
||||
dynamicAddItem () {
|
||||
let i = Object.keys(this.dynamic.email).length
|
||||
this.$set(this.dynamic.email, 'email' + i, '')
|
||||
// 依据自己的情况在dynamicRules里去增加验证对象
|
||||
this.$set(
|
||||
this.dynamicRules,
|
||||
'email.email' + i,
|
||||
this.dynamicRules['email.email0']
|
||||
)
|
||||
},
|
||||
dynamicPopItem () {
|
||||
let keys = Object.keys(this.dynamic.email)
|
||||
let k = keys.pop()
|
||||
if (k) {
|
||||
this.$delete(this.dynamic.email, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -130,6 +130,10 @@ export default {
|
||||
{
|
||||
name: 'Tooltip',
|
||||
path: '/n-tooltip'
|
||||
},
|
||||
{
|
||||
name: 'Form',
|
||||
path: '/n-form'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -26,6 +26,7 @@ import datePickerDemo from './components/datePickerDemo'
|
||||
import inputNumberDemo from './components/inputNumberDemo'
|
||||
import nimbusIconDemo from './components/nimbusIconDemo'
|
||||
import radioDemo from './components/radioDemo'
|
||||
import formDemo from './components/formDemo'
|
||||
import timePickerDemo from './components/timePickerDemo'
|
||||
|
||||
import notificationDemo from './components/notificationDemo'
|
||||
@ -79,6 +80,7 @@ const routes = [
|
||||
{ path: '/n-input-number', component: inputNumberDemo },
|
||||
{ path: '/n-nimbus-icon', component: nimbusIconDemo },
|
||||
{ path: '/n-radio', component: radioDemo },
|
||||
{ path: '/n-form', component: formDemo },
|
||||
{ path: '/n-time-picker', component: timePickerDemo }
|
||||
]
|
||||
},
|
||||
|
@ -22,7 +22,7 @@ You <strong>MUST</strong> fix all lint warnings and errors before you push your
|
||||
Run <code>npm run test-cov</code> to test all components and see detailed test coverage report.</p>
|
||||
<h2 id="wanttoseehowcomponentworks">Want to see how component works</h2>
|
||||
<ol>
|
||||
<li>Run <code>npm run build</code></li>
|
||||
<li>Run <code>npm run dev</code></li>
|
||||
<li>Open <code>http://localhost:8086/</code> in browser.</li>
|
||||
</ol>
|
||||
<h2 id="wanttoaddyourowncomponent">Want to add your own component</h2>
|
||||
|
3
index.js
3
index.js
@ -23,8 +23,8 @@ import Alert from './packages/common/Alert'
|
||||
import DatePicker from './packages/common/DatePicker'
|
||||
import InputNumber from './packages/common/InputNumber'
|
||||
import Radio from './packages/common/Radio'
|
||||
import Form from './packages/common/Form'
|
||||
import TimePicker from './packages/common/TimePicker'
|
||||
|
||||
import ServiceCard from './packages/nimbus/ServiceCard'
|
||||
import HomeLayout from './packages/nimbus/HomeLayout'
|
||||
import Navbar from './packages/nimbus/Navbar'
|
||||
@ -66,6 +66,7 @@ function install (Vue) {
|
||||
InputNumber.install(Vue)
|
||||
NimbusIcon.install(Vue)
|
||||
Radio.install(Vue)
|
||||
Form.install(Vue)
|
||||
TimePicker.install(Vue)
|
||||
}
|
||||
|
||||
|
10
packages/common/Form/index.js
Normal file
10
packages/common/Form/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
/* istanbul ignore file */
|
||||
import Form from './src/main.vue'
|
||||
import FormItem from './src/form-item.vue'
|
||||
|
||||
Form.install = function (Vue) {
|
||||
Vue.component(Form.name, Form)
|
||||
Vue.component(FormItem.name, FormItem)
|
||||
}
|
||||
|
||||
export default Form
|
194
packages/common/Form/src/form-item.vue
Normal file
194
packages/common/Form/src/form-item.vue
Normal file
@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div
|
||||
:class="getFormClass()"
|
||||
>
|
||||
<label
|
||||
v-if="label !== undefined"
|
||||
:class="`${prefix}__label`"
|
||||
:style="style"
|
||||
>
|
||||
{{ label }}
|
||||
</label>
|
||||
<div
|
||||
class="n-form-item__content"
|
||||
:class="validateFlag ? `${prefix}__content--error` : `${prefix}__content--pass`"
|
||||
>
|
||||
<slot />
|
||||
<div :class="`${prefix}__validate`">
|
||||
{{ validateInfo }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import AsyncValidator from 'async-validator'
|
||||
import { getObjValue } from '../../../utils/index'
|
||||
|
||||
export default {
|
||||
name: 'NFormItem',
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
labelWidth: {
|
||||
type: Number,
|
||||
default: undefined
|
||||
},
|
||||
labelStyle: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
labelPosition: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
prop: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: undefined
|
||||
},
|
||||
requiredLogo: {
|
||||
type: Boolean,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
inject: ['form'],
|
||||
provide () {
|
||||
return {
|
||||
formItem: this
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefix: 'n-form-item',
|
||||
validateInfo: '',
|
||||
validateFlag: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
style () {
|
||||
let s = {
|
||||
width: null
|
||||
}
|
||||
let lW = this.getValue('labelWidth')
|
||||
s.width = lW ? lW + 'px' : 'auto'
|
||||
return s
|
||||
},
|
||||
requiredRule () {
|
||||
let rule = []
|
||||
if (this.required) {
|
||||
rule.push({
|
||||
trigger: 'blur',
|
||||
required: true
|
||||
})
|
||||
}
|
||||
return rule
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// disabled (n) {
|
||||
// this.$children.forEach(i => {
|
||||
// if (getObjValue(i, '$options.name.0'.split('.')) === 'N') {
|
||||
// // dirctly modify the prop value is forbbiden by vue,
|
||||
// // neither definePropery or proxy pass
|
||||
// // we need to update every components we want to influence
|
||||
// // i.disabled = n
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
},
|
||||
created () {
|
||||
this.validateEventListener()
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$off('on-form-blur', this.onFormBlur)
|
||||
this.$off('on-form-change', this.onFormChange)
|
||||
},
|
||||
methods: {
|
||||
getValue (key) {
|
||||
return this[key] === undefined ? this.form[key] : this[key]
|
||||
},
|
||||
getFormClass () {
|
||||
let cls = ['n-form-item']
|
||||
let pre = 'n-form-item__label--'
|
||||
cls.push(pre + this.getValue('labelPosition'))
|
||||
if (!this.getValue('requiredLogo')) {
|
||||
return cls
|
||||
}
|
||||
if (this.required) {
|
||||
cls.push(pre + 'require')
|
||||
} else if (this.form && this.form.rules && this.prop) {
|
||||
let flag = (this.form.rules[this.prop] || []).some(i => {
|
||||
return i.required
|
||||
})
|
||||
if (flag) {
|
||||
cls.push(pre + 'require')
|
||||
}
|
||||
}
|
||||
return cls
|
||||
},
|
||||
getRules () {
|
||||
let rules = []
|
||||
if (this.required) {
|
||||
rules.push(this.requiredRule)
|
||||
}
|
||||
if (this.form && this.form.rules && this.prop) {
|
||||
(this.form.rules[this.prop] || []).forEach(i => {
|
||||
rules.push(i)
|
||||
})
|
||||
}
|
||||
return rules
|
||||
},
|
||||
onFormBlur () {
|
||||
this.validate('blur')
|
||||
},
|
||||
onFormChange () {
|
||||
this.validate('change')
|
||||
},
|
||||
/**
|
||||
* form item validation, can specify rules
|
||||
*/
|
||||
validate (trigger = '', cb = () => {}) {
|
||||
if (!this.prop || typeof this.prop !== 'string') {
|
||||
return
|
||||
}
|
||||
let rules = this.getRules()
|
||||
// 针对多层对象的验证
|
||||
let prop = this.prop
|
||||
let value = getObjValue(this.form.model, this.prop.split('.'))
|
||||
if (this.prop.indexOf('.') > -1) {
|
||||
prop = prop.slice(prop.lastIndexOf('.') + 1)
|
||||
}
|
||||
let activeRule = trigger === '' ? rules : rules.filter(i => {
|
||||
return i.trigger === trigger
|
||||
})
|
||||
if (activeRule.length === 0) return
|
||||
const asyncValidator = new AsyncValidator({ [prop]: activeRule })
|
||||
asyncValidator.validate({ [prop]: value }, (errors, fields) => {
|
||||
if (errors) {
|
||||
this.validateInfo = errors[0].message
|
||||
this.validateFlag = true
|
||||
} else {
|
||||
this.clearValidateClass()
|
||||
}
|
||||
cb(errors[0].message || false, fields)
|
||||
})
|
||||
},
|
||||
clearValidateClass () {
|
||||
this.validateInfo = ''
|
||||
this.validateFlag = false
|
||||
},
|
||||
validateEventListener () {
|
||||
const rules = this.getRules()
|
||||
if (rules.length >= 0) {
|
||||
this.$on('on-form-blur', this.onFormBlur)
|
||||
this.$on('on-form-change', this.onFormChange)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
124
packages/common/Form/src/main.vue
Normal file
124
packages/common/Form/src/main.vue
Normal file
@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<form
|
||||
class="n-form"
|
||||
:class="{
|
||||
'n-form--inline': inline
|
||||
}"
|
||||
>
|
||||
<slot />
|
||||
</form>
|
||||
</template>
|
||||
<script>
|
||||
import { deepClone, getObjValue } from '../../../utils/index'
|
||||
|
||||
export default {
|
||||
name: 'NForm',
|
||||
provide () {
|
||||
return {
|
||||
form: this
|
||||
}
|
||||
},
|
||||
props: {
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
labelWidth: {
|
||||
type: Number,
|
||||
default: 80
|
||||
},
|
||||
labelPosition: {
|
||||
type: String,
|
||||
default: 'right' // ['top', 'right', 'left', 'center']
|
||||
},
|
||||
model: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
requiredLogo: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
initialValue: ''
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.initialValue = deepClone(this.model)
|
||||
},
|
||||
methods: {
|
||||
getLabelPosClass (labelPosition) {
|
||||
return 'n-form--lable-' + labelPosition
|
||||
},
|
||||
/**
|
||||
* form validation, validate all prop-elements by default,
|
||||
* can use specify the scope of validation by param part.
|
||||
*
|
||||
* @param {Funtion} cb callback
|
||||
* @param {Array} scope to specify the scope of validation
|
||||
* @return {Boolean} validation passed or not
|
||||
*/
|
||||
validate (cb, scope = []) {
|
||||
let promise
|
||||
let isCallback = typeof cb === 'function'
|
||||
if (!isCallback && window.Promise) {
|
||||
promise = new Promise((resolve, reject) => {
|
||||
cb = valid => valid ? resolve(valid) : reject(valid)
|
||||
})
|
||||
}
|
||||
let valid = true
|
||||
let fields = {}
|
||||
this.$children.forEach((child, i) => {
|
||||
let flag = scope.length > 0 ? scope.indexOf(child.prop) > -1 : true
|
||||
if (child.prop && flag) {
|
||||
child.validate('', (errors, field) => {
|
||||
if (errors) {
|
||||
valid = false
|
||||
}
|
||||
fields = Object.assign({}, fields, field)
|
||||
})
|
||||
}
|
||||
if (++i === this.$children.length && isCallback) {
|
||||
cb(valid, fields)
|
||||
}
|
||||
})
|
||||
|
||||
if (promise) {
|
||||
return promise
|
||||
}
|
||||
},
|
||||
/**
|
||||
* just can reset the value with prop in form-item
|
||||
*/
|
||||
resetForm () {
|
||||
this.$children.forEach(child => {
|
||||
if (child.prop) {
|
||||
let keys = child.prop.split('.')
|
||||
let obj = this.model
|
||||
let j = 0
|
||||
keys.forEach((k, i) => {
|
||||
if (i !== keys.length - 1) {
|
||||
obj = obj[k]
|
||||
}
|
||||
j = i
|
||||
})
|
||||
obj[keys[j]] = getObjValue(this.initialValue, keys)
|
||||
if (child.validateFlag) {
|
||||
child.clearValidateClass()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -66,12 +66,22 @@
|
||||
|
||||
<script>
|
||||
import nIcon from '../../Icon'
|
||||
import Emitter from '../../../mixins/emitter'
|
||||
|
||||
export default {
|
||||
name: 'NInput',
|
||||
components: {
|
||||
nIcon
|
||||
},
|
||||
mixins: [ Emitter ],
|
||||
inject: {
|
||||
form: {
|
||||
default: null
|
||||
},
|
||||
formItem: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'input'
|
||||
@ -119,6 +129,11 @@ export default {
|
||||
isComposing: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
validateState () {
|
||||
return this.formItem ? this.formItem.validateState : ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCompositionStart () {
|
||||
this.isComposing = true
|
||||
@ -133,6 +148,10 @@ export default {
|
||||
},
|
||||
handleBlur (e) {
|
||||
this.$emit('blur', e)
|
||||
// 这里设计的冒泡还是针对特定元素, 否则会在其他不需要的元素上遍历
|
||||
if (this.formItem) {
|
||||
this.dispatch('NFormItem', 'on-form-blur', e.target.value)
|
||||
}
|
||||
},
|
||||
handleFocus (e) {
|
||||
this.$emit('focus', e)
|
||||
@ -142,6 +161,9 @@ export default {
|
||||
this.$emit('keyup', e)
|
||||
},
|
||||
handleChange (e) {
|
||||
if (this.formItem) {
|
||||
this.dispatch('NFormItem', 'on-form-change', e.target.value)
|
||||
}
|
||||
this.$emit('change', e.target.value)
|
||||
},
|
||||
handleClick (e) {
|
||||
|
@ -20,12 +20,20 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Emitter from '../../../mixins/emitter'
|
||||
|
||||
export default {
|
||||
name: 'NRadio',
|
||||
mixins: [ Emitter ],
|
||||
model: {
|
||||
prop: 'privateValue',
|
||||
event: 'input'
|
||||
},
|
||||
inject: {
|
||||
formItem: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: [Boolean, String, Number],
|
||||
@ -50,6 +58,9 @@ export default {
|
||||
if (this.disabled) return
|
||||
if (this.privateValue !== this.value) {
|
||||
this.$emit('input', this.value)
|
||||
if (this.formItem) {
|
||||
this.dispatch('NFormItem', 'on-form-change', this.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,17 +85,23 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Emitter from '../../../mixins/emitter'
|
||||
import detachable from '../../../mixins/detachable'
|
||||
import placeable from '../../../mixins/placeable'
|
||||
import toggleable from '../../../mixins/toggleable'
|
||||
|
||||
export default {
|
||||
name: 'NSingleSelect',
|
||||
mixins: [detachable, toggleable, placeable],
|
||||
mixins: [detachable, toggleable, placeable, Emitter],
|
||||
model: {
|
||||
prop: 'selectedValue',
|
||||
event: 'input'
|
||||
},
|
||||
inject: {
|
||||
formItem: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
@ -159,9 +165,12 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedItem () {
|
||||
selectedItem (n, o) {
|
||||
if (this.selectedItem !== null) {
|
||||
this.label = this.selectedItem.label
|
||||
if (n !== o && this.formItem) {
|
||||
this.dispatch('NFormItem', 'on-form-change', n.value)
|
||||
}
|
||||
} else {
|
||||
this.label = ''
|
||||
}
|
||||
|
33
packages/mixins/emitter.js
Normal file
33
packages/mixins/emitter.js
Normal file
@ -0,0 +1,33 @@
|
||||
function broadcast (componentName, eventName, params) {
|
||||
this.$children.forEach(child => {
|
||||
let name = child.$options.componentName
|
||||
if (name === componentName) {
|
||||
child.$emit.apply(child, [eventName].concat(params))
|
||||
} else {
|
||||
broadcast.apply(child, [componentName, eventName].concat([params]))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
dispatch (componentName, eventName, params) {
|
||||
let parent = this.$parent || this.$root
|
||||
let name = parent.$options.name
|
||||
|
||||
while (parent && (!name || name !== componentName)) {
|
||||
parent = parent.$parent
|
||||
|
||||
if (parent) {
|
||||
name = parent.$options.name
|
||||
}
|
||||
}
|
||||
if (parent) {
|
||||
parent.$emit.apply(parent, [eventName].concat(params))
|
||||
}
|
||||
},
|
||||
broadcast (componentName, eventName, params) {
|
||||
broadcast.call(this, componentName, eventName, params)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,34 @@
|
||||
import getScrollParent from './getScrollParent'
|
||||
export {
|
||||
getScrollParent
|
||||
import getScrollParent from './dom/getScrollParent'
|
||||
|
||||
const isObject = (o) => {
|
||||
let type = Object.prototype.toString.call(o)
|
||||
return type === '[object Array]' || type === '[object Object]'
|
||||
}
|
||||
|
||||
const _isObject = (o) => {
|
||||
return (typeof o === 'object' || typeof o === 'function') && o !== null
|
||||
}
|
||||
|
||||
const deepClone = (obj) => {
|
||||
if (!isObject(obj)) {
|
||||
return obj
|
||||
}
|
||||
|
||||
let isArray = Array.isArray(obj)
|
||||
let cloneObj = isArray ? [] : {}
|
||||
for (let key in obj) {
|
||||
cloneObj[key] = _isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
|
||||
}
|
||||
|
||||
return cloneObj
|
||||
}
|
||||
|
||||
const getObjValue = (obj, keys) => {
|
||||
return keys.reduce((res, n) => (res !== undefined && res[n] !== undefined ? res[n] : null), obj)
|
||||
}
|
||||
|
||||
export {
|
||||
getScrollParent,
|
||||
deepClone,
|
||||
getObjValue
|
||||
}
|
||||
|
88
styles/Form.scss
Normal file
88
styles/Form.scss
Normal file
@ -0,0 +1,88 @@
|
||||
@import './mixins/mixins.scss';
|
||||
@import './theme/default.scss';
|
||||
|
||||
@include b(form) {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
&.n-form--inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-content: space-around;
|
||||
flex-wrap: nowrap;
|
||||
.n-form-item:not(:last-child) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.n-form-item__label--top {
|
||||
display: block;
|
||||
.n-form-item__label {
|
||||
display: block;
|
||||
overflow-wrap: unset;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.n-form-item__label--require .n-form-item__label::before {
|
||||
float: right;
|
||||
content: '*';
|
||||
color:rgba(255, 146, 164, 1);
|
||||
margin-left: 5px;
|
||||
}
|
||||
.n-form-item__label--left .n-form-item__label {
|
||||
text-align: left;
|
||||
}
|
||||
.n-form-item__label--right .n-form-item__label {
|
||||
text-align: right;
|
||||
}
|
||||
.n-form-item__label--center .n-form-item__label {
|
||||
text-align: center;
|
||||
}
|
||||
.n-form--disable {
|
||||
box-shadow: inset 0 0 0px 1px rgb(99, 96, 96);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
cursor: not-allowed;
|
||||
&:hover {
|
||||
box-shadow: inset 0 0 0px 1px rgb(99, 96, 96);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include b(form-item) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
.n-form-item__label {
|
||||
flex-grow: 0;
|
||||
padding: 10px 10px 10px 0;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.n-form-item__content {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.n-form-item__validate {
|
||||
position: absolute;
|
||||
bottom: -18px;
|
||||
margin-top: 6px;
|
||||
color: rgba(255, 146, 164, 1);
|
||||
font-size: 14px;
|
||||
}
|
||||
.n-form-item__content--pass {
|
||||
.n-form-item__validate {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
.n-form-item__content--error {
|
||||
.n-form-item__validate {
|
||||
visibility: visible;
|
||||
}
|
||||
// 后期可以通过属性优化, 精确定位
|
||||
input, select, textarea {
|
||||
box-shadow: inset 0 0 0px 1px rgba(255, 146, 164, 1);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
@import './DatePicker.scss';
|
||||
@import './InputNumber.scss';
|
||||
@import './Radio.scss';
|
||||
@import './Form.scss';
|
||||
@import './TimePicker.scss';
|
||||
|
||||
@import "./NimbusServiceLayout.scss";
|
||||
|
Loading…
Reference in New Issue
Block a user