UNPKG

7.41 kBMarkdownView Raw
1<!--docs:
2title: "Auto Init"
3layout: detail
4section: components
5excerpt: "Utilities for declarative, DOM-based initialization of components on simple web sites."
6path: /catalog/auto-init/
7-->
8
9# Auto Init
10
11`mdc-auto-init` is a utility package that provides declarative, DOM-based method of initialization
12for MDC Web components on simple web sites. Note that for more advanced use-cases and complex sites,
13manual instantiation of components will give you more flexibility. However, `mdc-auto-init` is great
14for static websites, prototypes, and other use-cases where simplicity and convenience is most
15appropriate.
16
17## Installation
18
19```
20npm install @material/auto-init
21```
22
23## Usage
24
25### Using as part of `material-components-web`
26
27If you are using mdc-auto-init as part of the [material-components-web](../material-components-web)
28package, simply write the necessary DOM needed for a component, and attach a `data-mdc-auto-init`
29attribute to the root element with its value set to the component's JavaScript class name (e.g.,
30`MDCTextField`). Then, after writing the markup, simply insert a script tag that calls
31`mdc.autoInit()`. Make sure you call `mdc.autoInit()` after all scripts are loaded so it works
32properly.
33
34```html
35<label class="mdc-text-field mdc-text-field--filled" data-mdc-auto-init="MDCTextField">
36 <span class="mdc-text-field__ripple"></span>
37 <input class="mdc-text-field__input" type="text" aria-labelledby="label">
38 <span id="label" class="mdc-floating-label">Input Label</span>
39 <span class="mdc-line-ripple"></span>
40</label>
41
42<!-- at the bottom of the page -->
43<script type="text/javascript">
44 window.mdc.autoInit();
45</script>
46```
47
48This will attach an [MDCTextField](../mdc-textfield) instance to the root `<div>` element.
49
50#### Accessing the component instance
51
52When `mdc-auto-init` attaches a component to an element, it assign that instance to the element
53using a property whose name is the value of `data-mdc-auto-init`. For example, given
54
55```html
56<label class="mdc-text-field mdc-text-field--filled" data-mdc-auto-init="MDCTextField">
57 <span class="mdc-text-field__ripple"></span>
58 <input class="mdc-text-field__input" type="text" aria-labelledby="label">
59 <span id="label" class="mdc-floating-label">Input Label</span>
60 <span class="mdc-line-ripple"></span>
61</label>
62```
63
64Once `mdc.autoInit()` is called, you can access the component instance via an `MDCTextField`
65property on that element.
66
67```js
68document.querySelector('.mdc-text-field').MDCTextField.disabled = true;
69```
70
71#### Calling subsequent `mdc.autoInit()`
72
73If you decide to add new components into the DOM after the initial `mdc.autoInit()`, you can make subsequent calls to `mdc.autoInit()`. This will not reinitialize existing components. This works since mdc-auto-init will add the `data-mdc-auto-init-state="initialized"` attribute, which tracks if the component has already been initialized. After calling `mdc.autoInit()` your component will then look like:
74
75```html
76<label class="mdc-text-field mdc-text-field--filled" data-mdc-auto-init="MDCTextField" data-mdc-auto-init-state="initialized">
77 ...
78</label>
79```
80
81### Using as a standalone module
82
83#### Registering Components
84
85If you are using `mdc-auto-init` outside of `material-components-web`, you must manually provide a
86mapping between `data-mdc-auto-init` attribute values and the components which they map to. This can
87be achieved via `mdcAutoInit.register`.
88
89```js
90import mdcAutoInit from '@material/auto-init';
91import {MDCTextField} from '@material/textfield';
92
93mdcAutoInit.register('MDCTextField', MDCTextField);
94```
95
96`mdcAutoInit.register()` tells `mdc-auto-init` that when it comes across an element with a
97`data-mdc-auto-init` attribute set to `"MDCTextField"`, it should initialize an `MDCTextField`
98instance on that element. The `material-components-web` package does this for all components for
99convenience.
100
101Also note that a component can be mapped to any string, not necessarily the name of its constructor.
102
103```js
104import mdcAutoInit from '@material/auto-init';
105import {MDCTextField} from '@material/textfield';
106
107mdcAutoInit.register('My amazing text field!!!', MDCTextField);
108```
109
110```html
111<label class="mdc-text-field mdc-text-field--filled" data-mdc-auto-init="My amazing text field!!!">
112 <!-- ... -->
113</label>
114<script>window.mdc.autoInit();</script>
115```
116
117### De-registering components
118
119Any component can be deregistered by calling `mdcAutoInit.deregister` with the name used to register
120the component.
121
122```js
123mdcAutoInit.deregister('MDCTextField');
124```
125
126This will simply remove the name -> component mapping. It will _not_ affect any already-instantiated
127components on the page.
128
129To unregister all name -> component mappings, you can use `mdcAutoInit.deregisterAll()`.
130
131## How `mdc-auto-init` works
132
133`mdc-auto-init` maintains a registry object which maps string identifiers, or **names**, to
134component constructors. When the default exported function - `mdcAutoInit()` - is called,
135`mdc-auto-init` queries the DOM for all elements with a `data-mdc-auto-init` attribute. For each
136element returned, the following steps are taken:
137
1381. If the `data-mdc-auto-init` attribute does not have a value associated with it, throw an error
1392. If the value of `data-mdc-auto-init` cannot be found in the registry, throw an error
1403. If the element has an existing property whose name is the value of `data-mdc-auto-init`, it is
141 assumed to have already been initialized. Therefore it is skipped, and a warning will be logged
142 to the console (this behavior can be overridden).
1434. Let `Ctor` be the component constructor associated with the given name in the register
1445. Let `instance` be the result of calling `Ctor.attachTo()` and passing in the element as an
145 argument.
1466. Create a non-writable, non-enumerable property on the node whose name is the value of
147 `data-mdc-auto-init` and whose value is `instance`.
148
149### Initializing only a certain part of the page
150
151By default, `mdc-auto-init` will query the entire document to figure out which components to
152initialize. To override this behavior, you can pass in an optional `root` first argument specifying
153the root node whose children will be queried for instantiation.
154
155```html
156<div id="mdc-section">
157 <!-- MDC Web Components, etc. -->
158</div>
159<script>window.mdc.autoInit(document.getElementById('mdc-section'));</script>
160```
161
162In the above example, only elements within `<div id="mdc-section">` will be queried.
163
164### Calling autoInit() multiple times
165
166By default, `mdc-auto-init` only expects to be called once, at page-load time. However, there may be
167certain scenarios where one may want to use `mdc-auto-init` and may still need to call it multiple
168times, such as on a Wordpress site that contains an infinitely-scrolling list of new blog post
169elements containing MDC Web components. `mdcAutoInit()` takes an optional second argument which is the
170function used to warn users when a component is initialized multiple times. By default, this is just
171`console.warn()`. However, to skip over already-initialized components without logging a
172warning, you could simply pass in a nop.
173
174```html
175<script>window.mdc.autoInit(/* root */ document, () => {});</script>
176```
177
178This will suppress any warnings about already initialized elements.
179
180### Events
181
182#### MDCAutoInit:End
183Triggered when initialization of all components is complete.
184
185`document.addEventListener("MDCAutoInit:End", () => {...});`