1 |
|
2 | title: "Auto Init"
|
3 | layout: detail
|
4 | section: components
|
5 | excerpt: "Utilities for declarative, DOM-based initialization of components on simple web sites."
|
6 | path: /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
|
12 | for MDC Web components on simple web sites. Note that for more advanced use-cases and complex sites,
|
13 | manual instantiation of components will give you more flexibility. However, `mdc-auto-init` is great
|
14 | for static websites, prototypes, and other use-cases where simplicity and convenience is most
|
15 | appropriate.
|
16 |
|
17 | ## Installation
|
18 |
|
19 | ```
|
20 | npm install @material/auto-init
|
21 | ```
|
22 |
|
23 | ## Usage
|
24 |
|
25 | ### Using as part of `material-components-web`
|
26 |
|
27 | If you are using mdc-auto-init as part of the [material-components-web](../material-components-web)
|
28 | package, simply write the necessary DOM needed for a component, and attach a `data-mdc-auto-init`
|
29 | attribute 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
|
32 | properly.
|
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 |
|
48 | This will attach an [MDCTextField](../mdc-textfield) instance to the root `<div>` element.
|
49 |
|
50 | #### Accessing the component instance
|
51 |
|
52 | When `mdc-auto-init` attaches a component to an element, it assign that instance to the element
|
53 | using 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 |
|
64 | Once `mdc.autoInit()` is called, you can access the component instance via an `MDCTextField`
|
65 | property on that element.
|
66 |
|
67 | ```js
|
68 | document.querySelector('.mdc-text-field').MDCTextField.disabled = true;
|
69 | ```
|
70 |
|
71 | #### Calling subsequent `mdc.autoInit()`
|
72 |
|
73 | If 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 |
|
85 | If you are using `mdc-auto-init` outside of `material-components-web`, you must manually provide a
|
86 | mapping between `data-mdc-auto-init` attribute values and the components which they map to. This can
|
87 | be achieved via `mdcAutoInit.register`.
|
88 |
|
89 | ```js
|
90 | import mdcAutoInit from '@material/auto-init';
|
91 | import {MDCTextField} from '@material/textfield';
|
92 |
|
93 | mdcAutoInit.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`
|
98 | instance on that element. The `material-components-web` package does this for all components for
|
99 | convenience.
|
100 |
|
101 | Also note that a component can be mapped to any string, not necessarily the name of its constructor.
|
102 |
|
103 | ```js
|
104 | import mdcAutoInit from '@material/auto-init';
|
105 | import {MDCTextField} from '@material/textfield';
|
106 |
|
107 | mdcAutoInit.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 |
|
119 | Any component can be deregistered by calling `mdcAutoInit.deregister` with the name used to register
|
120 | the component.
|
121 |
|
122 | ```js
|
123 | mdcAutoInit.deregister('MDCTextField');
|
124 | ```
|
125 |
|
126 | This will simply remove the name -> component mapping. It will _not_ affect any already-instantiated
|
127 | components on the page.
|
128 |
|
129 | To 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
|
134 | component 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
|
136 | element returned, the following steps are taken:
|
137 |
|
138 | 1. If the `data-mdc-auto-init` attribute does not have a value associated with it, throw an error
|
139 | 2. If the value of `data-mdc-auto-init` cannot be found in the registry, throw an error
|
140 | 3. 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).
|
143 | 4. Let `Ctor` be the component constructor associated with the given name in the register
|
144 | 5. Let `instance` be the result of calling `Ctor.attachTo()` and passing in the element as an
|
145 | argument.
|
146 | 6. 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 |
|
151 | By default, `mdc-auto-init` will query the entire document to figure out which components to
|
152 | initialize. To override this behavior, you can pass in an optional `root` first argument specifying
|
153 | the 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 |
|
162 | In the above example, only elements within `<div id="mdc-section">` will be queried.
|
163 |
|
164 | ### Calling autoInit() multiple times
|
165 |
|
166 | By default, `mdc-auto-init` only expects to be called once, at page-load time. However, there may be
|
167 | certain scenarios where one may want to use `mdc-auto-init` and may still need to call it multiple
|
168 | times, such as on a Wordpress site that contains an infinitely-scrolling list of new blog post
|
169 | elements containing MDC Web components. `mdcAutoInit()` takes an optional second argument which is the
|
170 | function 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
|
172 | warning, you could simply pass in a nop.
|
173 |
|
174 | ```html
|
175 | <script>window.mdc.autoInit(/* root */ document, () => {});</script>
|
176 | ```
|
177 |
|
178 | This will suppress any warnings about already initialized elements.
|
179 |
|
180 | ### Events
|
181 |
|
182 | #### MDCAutoInit:End
|
183 | Triggered when initialization of all components is complete.
|
184 |
|
185 | `document.addEventListener("MDCAutoInit:End", () => {...});`
|