Skip to content

Commit 8a438ae

Browse files
VdustRSamuell1
authored andcommitted
refactor(MdDatepicker): Better flow (#1698)
* refactor(MdDatepicker): computed locale options * style(MdDatepicker): fix style * refactor(MdDatepicker): Better flow for datepicker BREAKING CHANGE: upgrade date-fns to 2.0.0-alpha.7 fix #1689 * feat(MdDatepicker): new props md-model-type * fix(MdDatepicker): fix warn message template literals * docs(Datepicker): fix props md-model-type * style(MdDatepicker): lint * fix(MdDatepicker): mdModelType validator name * feat(MdDatepicker): dynamic date format supported * docs(Datepicker): date format example * docs(Configuration): * docs(Configuration): better description
1 parent 714ee9f commit 8a438ae

File tree

11 files changed

+394
-63
lines changed

11 files changed

+394
-63
lines changed

docs/app/i18n/en-US/pages.js

+6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ export default {
2727
installation: 'Installation',
2828
npmOrYarn: 'NPM or Yarn'
2929
},
30+
configuration: {
31+
title: 'Configuration',
32+
viaVueGlobalObject: 'Via Vue global object',
33+
inVueComponents: 'In Vue components',
34+
options: 'Options',
35+
},
3036
themes: {
3137
title: 'Themes'
3238
},

docs/app/pages/Components/Datepicker/Datepicker.vue

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<example src="./examples/BasicDatepicker.vue" />
22
<example src="./examples/LabeledDatepicker.vue" />
3+
<example src="./examples/MultiTypesDatepicker.vue" />
34
<example src="./examples/CancelOpenDatepicker.vue" />
45
<example src="./examples/CloseOnSelectDatepicker.vue" />
56
<example src="./examples/DisabledDatesDatepicker.vue" />
@@ -18,6 +19,12 @@
1819
<code-example title="Labeled Example" :component="examples['labeled-datepicker']" />
1920
</div>
2021

22+
<div class="page-container-section">
23+
<h2>Model Types</h2>
24+
<p>Vue Material datepicker supports multiple types of <code>v-model</code>, whiches default is <code>Date</code>. If you want to communicate with other services without timezone problems, you could use <code>String</code> to avoid them:</p>
25+
<code-example title="With different type binding" :component="examples['multi-types-datepicker']" />
26+
</div>
27+
2128
<div class="page-container-section">
2229
<h2>Cancel open on focus</h2>
2330
<p>By default Datepicker component open on focus to it's input. This will make the input useless and the user will not be able to type the date manually. You can disable this behavior:</p>
@@ -57,10 +64,16 @@
5764
props: [
5865
{
5966
name: 'v-model',
60-
type: 'Date',
67+
type: 'Date|Number|String',
6168
description: 'The model variable to bind the selected date',
6269
defaults: 'null'
6370
},
71+
{
72+
name: 'md-model-type',
73+
type: 'Constructor',
74+
description: 'Model type. This props will be overwritten by <code>typeof v-model</code>. It could be <code>Date</code>, <code>Number</code> or <code>String</code>.',
75+
defaults: 'Date'
76+
},
6477
{
6578
name: 'md-disabled-dates',
6679
type: 'Array|Function',

docs/app/pages/Components/Datepicker/examples/BasicDatepicker.vue

+18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99
</md-select>
1010
<span class="md-helper-text">This config is global.</span>
1111
</md-field>
12+
<md-field>
13+
<label for="movie">Date format</label>
14+
<md-select v-model="dateFormat">
15+
<md-option value="YYYY-MM-DD">default</md-option>
16+
<md-option value="YYYY/MM/DD">YYYY/MM/DD</md-option>
17+
<md-option value="DD/MM/YYYY">DD/MM/YYYY</md-option>
18+
<md-option value="MM/DD/YYYY">MM/DD/YYYY</md-option>
19+
</md-select>
20+
<span class="md-helper-text">This config is global.</span>
21+
</md-field>
1222
</div>
1323
</template>
1424

@@ -26,6 +36,14 @@
2636
set (val) {
2737
this.$material.locale.firstDayOfAWeek = val
2838
}
39+
},
40+
dateFormat: {
41+
get () {
42+
return this.$material.locale.dateFormat
43+
},
44+
set (val) {
45+
this.$material.locale.dateFormat = val
46+
}
2947
}
3048
}
3149
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<template>
2+
<div>
3+
<div class="block">
4+
<h3>Date</h3>
5+
<md-datepicker v-model="date" />
6+
<div class="value">value: {{date}}</div>
7+
</div>
8+
<md-divider />
9+
<div class="block">
10+
<h3>String</h3>
11+
<md-datepicker v-model="string" />
12+
<div class="value">value: {{string}}</div>
13+
</div>
14+
<md-divider />
15+
<div class="block">
16+
<h3>Number</h3>
17+
<md-datepicker v-model="number" />
18+
<div class="value">value: {{number}}</div>
19+
</div>
20+
<md-divider />
21+
<div class="block">
22+
<h3>Dynamic By Model</h3>
23+
<md-radio :model="type" value="date" @change="toDate">Date</md-radio>
24+
<md-radio :model="type" value="string" @change="toString">String</md-radio>
25+
<md-radio :model="type" value="number" @change="toNumber">Number</md-radio>
26+
<md-datepicker v-model="dynamicByModel" />
27+
<div class="value">value: {{dynamicByModel}}</div>
28+
</div>
29+
<md-divider />
30+
<div class="block">
31+
<h3>Dynamic By <code>:md-model-type</code></h3>
32+
<md-radio v-model="mdTypeValue" value="date">Date</md-radio>
33+
<md-radio v-model="mdTypeValue" value="string">String</md-radio>
34+
<md-radio v-model="mdTypeValue" value="number">Number</md-radio>
35+
<md-datepicker v-model="dynamicByMdType" :md-model-type="mdType" />
36+
<div class="value">value: {{dynamicByMdType}}</div>
37+
</div>
38+
</div>
39+
</template>
40+
41+
<script>
42+
import parse from 'date-fns/parse'
43+
import format from 'date-fns/format'
44+
import isValid from 'date-fns/isValid'
45+
46+
export default {
47+
name: 'MultiTypesDatepicker',
48+
data () {
49+
let dateFormat = this.$material.locale.dateFormat || 'YYYY-MM-DD'
50+
let now = new Date()
51+
52+
return {
53+
date: now,
54+
string: format(now, dateFormat),
55+
number: Number(now),
56+
dynamicByModel: now,
57+
mdTypeValue: 'date',
58+
dynamicByMdType: now
59+
}
60+
},
61+
computed: {
62+
firstDayOfAWeek: {
63+
get () {
64+
return this.$material.locale.firstDayOfAWeek
65+
},
66+
set (val) {
67+
this.$material.locale.firstDayOfAWeek = val
68+
}
69+
},
70+
// eslint-disable-next-line
71+
type () {
72+
if (typeof this.dynamicByModel === 'object' && this.dynamicByModel instanceof Date && isValid(this.dynamicByModel)) {
73+
return 'date'
74+
} else if (typeof this.dynamicByModel === 'string') {
75+
return 'string'
76+
} else if (Number.isInteger(this.dynamicByModel) && this.dynamicByModel >= 0) {
77+
return 'number'
78+
} else if (this.model === null || this.model === undefined) {
79+
return 'null'
80+
} else {
81+
throw new Error('Type error')
82+
}
83+
},
84+
dateFormat () {
85+
return this.$material.locale.dateFormat || 'YYYY-MM-DD'
86+
},
87+
mdType () {
88+
switch (this.mdTypeValue) {
89+
case 'date':
90+
return Date
91+
case 'string':
92+
return String
93+
case 'number':
94+
return Number
95+
}
96+
}
97+
},
98+
methods: {
99+
toDate () {
100+
switch (this.type) {
101+
case 'null':
102+
this.dynamicByModel = null
103+
break
104+
105+
case 'string':
106+
this.dynamicByModel = parse(this.dynamicByModel, this.dateFormat, new Date())
107+
break
108+
109+
case 'number':
110+
this.dynamicByModel = new Date(this.dynamicByModel)
111+
break
112+
}
113+
},
114+
toString () {
115+
this.toDate()
116+
this.dynamicByModel = this.dynamicByModel && format(this.dynamicByModel, this.dateFormat)
117+
},
118+
toNumber () {
119+
this.toDate()
120+
this.dynamicByModel = this.dynamicByModel && Number(this.dynamicByModel)
121+
}
122+
}
123+
}
124+
</script>

docs/app/pages/Configuration.vue

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<template>
2+
<page-container centered :title="$t('pages.configuration.title')">
3+
<div class="page-container-section">
4+
<h2 class="md-headline">Global configuration</h2>
5+
6+
<p>Vue Material is providing some global options for customization. These options are reactive, you can change it anytime, anywhere:</p>
7+
<code-example :title="$t('pages.configuration.viaVueGlobalObject')">
8+
import Vue from 'vue'
9+
10+
// change single option
11+
Vue.material.locale.dateFormat = 'DD/MM/YYYY'
12+
13+
// change multiple options
14+
Vue.material = {
15+
...Vue.material,
16+
locale: {
17+
...Vue.material.locale,
18+
dateFormat: 'DD/MM/YYYY',
19+
firstDayOfAWeek: 1
20+
}
21+
}
22+
</code-example>
23+
<p>or you can change it via <code>this.$material</code> in a vue component:</p>
24+
<code-example :title="$t('pages.configuration.inVueComponents')">
25+
export default {
26+
name: 'ChangeDateFormat',
27+
computed: {
28+
dateFormat: {
29+
get () {
30+
return this.$material.locale.dateFormat
31+
},
32+
set (val) {
33+
this.$material.locale.dateFormat = val
34+
}
35+
}
36+
}
37+
}
38+
</code-example>
39+
40+
<p>Here are options Vue Material provide for customization:</p>
41+
42+
<code-example :title="$t('pages.configuration.options')">
43+
{
44+
// activeness of ripple effect
45+
ripple: true,
46+
47+
theming: {},
48+
locale: {
49+
// range for datepicker
50+
startYear: 1900,
51+
endYear: 2099,
52+
53+
// date format for date picker
54+
dateFormat: 'YYYY-MM-DD',
55+
56+
// i18n strings
57+
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
58+
shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
59+
shorterDays: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
60+
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
61+
shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
62+
shorterMonths: ['J', 'F', 'M', 'A', 'M', 'Ju', 'Ju', 'A', 'Se', 'O', 'N', 'D'],
63+
64+
// `0` stand for Sunday, `1` stand for Monday
65+
firstDayOfAWeek: 0
66+
}
67+
}
68+
</code-example>
69+
</div>
70+
71+
</page-container>
72+
</template>
73+
74+
<script>
75+
export default {
76+
name: 'Configuration'
77+
}
78+
</script>

docs/app/routes.js

+5
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ export const routes = [
114114
name: 'getting-started',
115115
page: 'GettingStarted.vue'
116116
},
117+
{
118+
path: '/configuration',
119+
name: 'configuration',
120+
page: 'Configuration.vue'
121+
},
117122
{
118123
path: '/themes',
119124
name: 'themes',

docs/app/template/MainNavContent.vue

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
<div class="main-nav-content">
33
<router-link to="/" exact>{{ $t('pages.home.title') }}</router-link>
44
<router-link to="/getting-started">{{ $t('pages.gettingStarted.title') }}</router-link>
5+
<div class="main-nav-level">
6+
<router-link to="/configuration">{{ $t('pages.configuration.title') }}</router-link>
7+
</div>
58

69
<router-link to="/themes">{{ $t('pages.themes.title') }}</router-link>
710
<div class="main-nav-level">

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"css-loader": "^0.28.9",
6767
"css-mqpacker": "^6.0.2",
6868
"cz-conventional-changelog": "^2.1.0",
69-
"date-fns": "^1.29.0",
69+
"date-fns": "^2.0.0-alpha.7",
7070
"deepmerge": "^2.0.1",
7171
"eslint": "^4.16.0",
7272
"eslint-config-standard": "^11.0.0-beta.0",

0 commit comments

Comments
 (0)