Material Design

This sample uses C1 MVC's pseudo-classes to implement a form with dynamic labels, validation, and focus indicators similar to those in Google's Material Design spec.

Edit Item
We do need your name...
We need a valid e-mail...
Four groups of four digits...
1
2
3
4
5
// This file locates: "Scripts/Lesson/C1Input/MaterialDesign.js".
c1.documentReady(function () {
    var time = wijmo.Control.getControl('#time');
    time.value = null;
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// This file locates: "Content/css/Lesson/C1Input/MaterialDesign.css".
form {
  background-color: white;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
  max-width: 900px;
}
.wj-dialog-body {
  display: flex;
  flex-wrap: wrap;
}
.wj-dialog-body > .wj-labeled-input {
  width: 160px;
  margin: 0 .15in;
}
 
/* wj-labeled-input: adapted from MDL styles */
 
/* underline access keys */
.wj-labeled-input .accesskey {
    text-decoration: underline;
}
 
/* label input container */
.wj-labeled-input {
    position: relative;
    font-size: 16px;
    display: inline-block;
    box-sizing: border-box;
    width: 300px;
    max-width: 100%;
    margin: 0 20px;
    padding: 20px 0;
}
 
    /* Wijmo control in the container */
    .wj-labeled-input .wj-control.wj-content {
        margin: 0;
        width: 100%;
        background-color: transparent;
        border: none;
        border-bottom: 1px solid rgba(0,0,0,.1);
    }
    .wj-labeled-input .wj-control.wj-content button {
        opacity: 0.75;
        border-color: rgba(0,0,0,.1);
    }
 
    /* label in the container (must come after the control) */
    .wj-labeled-input label {
        font-size: 16px;
        top: 24px;
        bottom: 0;
        margin: 0;
        pointer-events: none;
        position: absolute;
        display: block;
        width: 100%;
        overflow: hidden;
        white-space: nowrap;
        text-align: left;
        color: rgba(0, 0, 0, 0.258824);
        transition-duration: .2s;
        transition-timing-function: cubic-bezier(.4,0,.2,1);
    }
     
    /* move label out of the way when control is focused or not empty */
    .wj-static-labels .wj-labeled-input :not(.wj-state-focused) + label,
    .wj-labeled-input .wj-state-focused + label,
    .wj-labeled-input :not(.wj-state-empty) + label {
        font-size: 12px;
        top: 4px;
        color: rgb(63,81,181);
        visibility: visible;
    }
    .wj-labeled-input .wj-state-invalid + label {
        color: #d50000;
    }
 
    /* underline label */
    .wj-labeled-input label:after {
        background-color: rgb(63,81,181);
        bottom: 20px;
        content: '';
        height: 2px;
        left: 45%;
        position: absolute;
        transition-duration: .2s;
        transition-timing-function: cubic-bezier(.4,0,.2,1);
        visibility: hidden;
        width: 10px;
    }
 
    /* show underline when focused */
    .wj-labeled-input .wj-state-focused + label:after {
        left: 0;
        visibility: visible;
        width: 100%;
    }
    .wj-labeled-input .wj-state-invalid + label:after {
        background-color: #d50000;
    }
 
    /* validation message */
    .wj-labeled-input .wj-error {
        color: #d50000;
        position: absolute;
        font-size: 12px;
        margin-top: 3px;
        visibility: hidden;
        display: block;
    }
    .wj-labeled-input .wj-control.wj-state-invalid ~ .wj-error {
        visibility: visible;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
using System.Web.Mvc;
 
namespace LearnMvcClient.Controllers
{
    public partial class C1InputController : Controller
    {
        // GET: MaterialDesign
        public ActionResult MaterialDesign()
        {
            return View();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
@{
    var countries = new[] { "US", "UK", "Japan", "Germany", "France", "Italy", "Russia", "China", "India", "Korea", "Spain", "Canada", "Denmark", "Sweden", "Holland", "Norway", "Portugal" };
    var colors = new[] { "Black", "White", "Grey", "Red", "Green", "Blue", "Yellow", "Pink", "Purple", "Orange" };
}
 
<h1>
    @Html.Raw(Resources.C1Input.MaterialDesign_Title)
</h1>
<p>
    @Html.Raw(Resources.C1Input.MaterialDesign_Text1)
</p>
<form>
    <div class="wj-dialog-header" tabindex="-1">
        @Html.Raw(Resources.C1Input.MaterialDesign_Text2)
    </div>
    <div class="wj-dialog-body">
        <!-- personal information -->
        <div class="wj-labeled-input">
            <div id="name" autocomplete="name" required accesskey="n">
            </div>
            <label for="name">@Html.Raw(Resources.C1Input.MaterialDesign_Text3)</label>
            <div class="wj-error" tabindex="-1">@Html.Raw(Resources.C1Input.MaterialDesign_Text4)</div>
            @Html.C1().ComboBox("#name").IsEditable(true).IsRequired(true).ShowDropDownButton(false)
        </div>
        <div class="wj-labeled-input">
            <div id="email" autocomplete="email" required pattern="\S+@Html.Raw("@")\S+\.\S+" accesskey="e">
            </div>
            <label for="email">@Html.Raw(Resources.C1Input.MaterialDesign_Text5)</label>
            <div class="wj-error" tabindex="-1">@Html.Raw(Resources.C1Input.MaterialDesign_Text6)</div>
            @Html.C1().ComboBox("#email").IsEditable(true).IsRequired(true).ShowDropDownButton(false)
        </div>
        <div class="wj-labeled-input">
            <div id="country" items-source="countries" accesskey="c">
            </div>
            <label for="country">@Html.Raw(Resources.C1Input.MaterialDesign_Text7)</label>
            @Html.C1().ComboBox("#country").Bind(countries).IsRequired(false).IsEditable(true).Text("")
        </div>
        <div class="wj-labeled-input">
            <div id="card" autocomplete="ccnumber" pattern="[0-9]{4} [0-9]{4} [0-9]{4} [0-9]{4}" accesskey="r">
            </div>
            <label for="card">@Html.Raw(Resources.C1Input.MaterialDesign_Text8)</label>
            <div class="wj-error" tabindex="-1">@Html.Raw(Resources.C1Input.MaterialDesign_Text9)</div>
            @Html.C1().InputMask("#card").IsRequired(false).Value("").Mask("9999 9999 9999 9999")
        </div>
 
        <!-- transaction information -->
        <div class="wj-labeled-input">
            <div id="date" accesskey="d">
            </div>
            <label for="date">@Html.Raw(Resources.C1Input.MaterialDesign_Text10)</label>
            @Html.C1().InputDate("#date").IsRequired(false).Value(null)
        </div>
        <div class="wj-labeled-input">
            <div id="time" accesskey="t">
            </div>
            <label for="time">@Html.Raw(Resources.C1Input.MaterialDesign_Text11)></label>
            @Html.C1().InputTime("#time").IsRequired(false).Min(new DateTime(1, 1, 1, 8, 0, 0)).Max(new DateTime(1, 1, 1, 18, 0, 0)).Value(null)
        </div>
        <div class="wj-labeled-input">
            <div id="qty" accesskey="q">
            </div>
            <label for="quantity">@Html.Raw(Resources.C1Input.MaterialDesign_Text12)</label>
            @Html.C1().InputNumber("#qty").IsRequired(false).Format("n0").Step(1).Value(null)
        </div>
        <div class="wj-labeled-input">
            <div id="discount" accesskey="i">
            </div>
            <label for="discount">@Html.Raw(Resources.C1Input.MaterialDesign_Text13)</label>
            @Html.C1().InputNumber("#discount").IsRequired(false).Format("p0").Step(0.05).Min(0).Max(0.2).Value(null)
        </div>
        <div class="wj-labeled-input">
            <div id="colors" accesskey="f">
            </div>
            <label for="colors">@Html.Raw(Resources.C1Input.MaterialDesign_Text14)</label>
            @Html.C1().MultiSelect("#colors").Bind(colors).HeaderFormat(Resources.C1Input.MaterialDesign_Text15)
        </div>
    </div>
 
    <div class="wj-dialog-footer">
        <button class="btn btn-primary" type="submit">@Resources.Resource.Btn_Ok</button>
        <button class="btn btn-default wj-hide-cancel">@Resources.Resource.Btn_Cancel</button>
    </div>
</form>