1 | declare module '@ember/-internals/glimmer/lib/component' {
|
2 | import { PROPERTY_DID_CHANGE } from '@ember/-internals/metal';
|
3 | import type { PropertyDidChange } from '@ember/-internals/metal/lib/property_events';
|
4 | import { TargetActionSupport } from '@ember/-internals/runtime';
|
5 | import {
|
6 | ActionSupport,
|
7 | ChildViewsSupport,
|
8 | ClassNamesSupport,
|
9 | CoreView,
|
10 | EventDispatcher,
|
11 | ViewMixin,
|
12 | ViewStateSupport,
|
13 | } from '@ember/-internals/views';
|
14 | import type { Template, TemplateFactory } from '@glimmer/interfaces';
|
15 | import type { DirtyableTag } from '@glimmer/validator';
|
16 | import {
|
17 | DIRTY_TAG,
|
18 | IS_DISPATCHING_ATTRS,
|
19 | } from '@ember/-internals/glimmer/lib/component-managers/curly';
|
20 | /**
|
21 | @module @ember/component
|
22 | */
|
23 | interface ComponentMethods {
|
24 | /**
|
25 | Called when the attributes passed into the component have been updated.
|
26 | Called both during the initial render of a container and during a rerender.
|
27 | Can be used in place of an observer; code placed here will be executed
|
28 | every time any attribute updates.
|
29 | @method didReceiveAttrs
|
30 | @public
|
31 | @since 1.13.0
|
32 | */
|
33 | didReceiveAttrs(): void;
|
34 | /**
|
35 | Called when the attributes passed into the component have been updated.
|
36 | Called both during the initial render of a container and during a rerender.
|
37 | Can be used in place of an observer; code placed here will be executed
|
38 | every time any attribute updates.
|
39 | @event didReceiveAttrs
|
40 | @public
|
41 | @since 1.13.0
|
42 | */
|
43 | /**
|
44 | Called after a component has been rendered, both on initial render and
|
45 | in subsequent rerenders.
|
46 | @method didRender
|
47 | @public
|
48 | @since 1.13.0
|
49 | */
|
50 | didRender(): void;
|
51 | /**
|
52 | Called after a component has been rendered, both on initial render and
|
53 | in subsequent rerenders.
|
54 | @event didRender
|
55 | @public
|
56 | @since 1.13.0
|
57 | */
|
58 | /**
|
59 | Called before a component has been rendered, both on initial render and
|
60 | in subsequent rerenders.
|
61 | @method willRender
|
62 | @public
|
63 | @since 1.13.0
|
64 | */
|
65 | willRender(): void;
|
66 | /**
|
67 | Called before a component has been rendered, both on initial render and
|
68 | in subsequent rerenders.
|
69 | @event willRender
|
70 | @public
|
71 | @since 1.13.0
|
72 | */
|
73 | /**
|
74 | Called when the attributes passed into the component have been changed.
|
75 | Called only during a rerender, not during an initial render.
|
76 | @method didUpdateAttrs
|
77 | @public
|
78 | @since 1.13.0
|
79 | */
|
80 | didUpdateAttrs(): void;
|
81 | /**
|
82 | Called when the attributes passed into the component have been changed.
|
83 | Called only during a rerender, not during an initial render.
|
84 | @event didUpdateAttrs
|
85 | @public
|
86 | @since 1.13.0
|
87 | */
|
88 | /**
|
89 | Called when the component is about to update and rerender itself.
|
90 | Called only during a rerender, not during an initial render.
|
91 | @method willUpdate
|
92 | @public
|
93 | @since 1.13.0
|
94 | */
|
95 | willUpdate(): void;
|
96 | /**
|
97 | Called when the component is about to update and rerender itself.
|
98 | Called only during a rerender, not during an initial render.
|
99 | @event willUpdate
|
100 | @public
|
101 | @since 1.13.0
|
102 | */
|
103 | /**
|
104 | Called when the component has updated and rerendered itself.
|
105 | Called only during a rerender, not during an initial render.
|
106 | @method didUpdate
|
107 | @public
|
108 | @since 1.13.0
|
109 | */
|
110 | didUpdate(): void;
|
111 | /**
|
112 | Called when the component has updated and rerendered itself.
|
113 | Called only during a rerender, not during an initial render.
|
114 | @event didUpdate
|
115 | @public
|
116 | @since 1.13.0
|
117 | */
|
118 | /**
|
119 | The HTML `id` of the component's element in the DOM. You can provide this
|
120 | value yourself but it must be unique (just as in HTML):
|
121 |
|
122 | ```handlebars
|
123 | {{my-component elementId="a-really-cool-id"}}
|
124 | ```
|
125 |
|
126 | ```handlebars
|
127 | <MyComponent @elementId="a-really-cool-id" />
|
128 | ```
|
129 | If not manually set a default value will be provided by the framework.
|
130 | Once rendered an element's `elementId` is considered immutable and you
|
131 | should never change it. If you need to compute a dynamic value for the
|
132 | `elementId`, you should do this when the component or element is being
|
133 | instantiated:
|
134 |
|
135 | ```javascript
|
136 | export default Component.extend({
|
137 | init() {
|
138 | this._super(...arguments);
|
139 |
|
140 | var index = this.get('index');
|
141 | this.set('elementId', `component-id${index}`);
|
142 | }
|
143 | });
|
144 | ```
|
145 |
|
146 | @property elementId
|
147 | @type String
|
148 | @public
|
149 | */
|
150 | layoutName?: string;
|
151 | }
|
152 | const SIGNATURE: unique symbol;
|
153 | /**
|
154 | A component is a reusable UI element that consists of a `.hbs` template and an
|
155 | optional JavaScript class that defines its behavior. For example, someone
|
156 | might make a `button` in the template and handle the click behavior in the
|
157 | JavaScript file that shares the same name as the template.
|
158 |
|
159 | Components are broken down into two categories:
|
160 |
|
161 | - Components _without_ JavaScript, that are based only on a template. These
|
162 | are called Template-only or TO components.
|
163 | - Components _with_ JavaScript, which consist of a template and a backing
|
164 | class.
|
165 |
|
166 | Ember ships with two types of JavaScript classes for components:
|
167 |
|
168 | 1. Glimmer components, imported from `@glimmer/component`, which are the
|
169 | default component's for Ember Octane (3.15) and more recent editions.
|
170 | 2. Classic components, imported from `@ember/component`, which were the
|
171 | default for older editions of Ember (pre 3.15).
|
172 |
|
173 | Below is the documentation for Classic components. If you are looking for the
|
174 | API documentation for Template-only or Glimmer components, it is [available
|
175 | here](/ember/release/modules/@glimmer%2Fcomponent).
|
176 |
|
177 | ## Defining a Classic Component
|
178 |
|
179 | If you want to customize the component in order to handle events, transform
|
180 | arguments or maintain internal state, you implement a subclass of `Component`.
|
181 |
|
182 | One example is to add computed properties to your component:
|
183 |
|
184 | ```app/components/person-profile.js
|
185 | import Component from '@ember/component';
|
186 |
|
187 | export default Component.extend({
|
188 | displayName: computed('person.title', 'person.firstName', 'person.lastName', function() {
|
189 | let { title, firstName, lastName } = this.person;
|
190 |
|
191 | if (title) {
|
192 | return `${title} ${lastName}`;
|
193 | } else {
|
194 | return `${firstName} ${lastName}`;
|
195 | }
|
196 | })
|
197 | });
|
198 | ```
|
199 |
|
200 | And then use it in the component's template:
|
201 |
|
202 | ```app/templates/components/person-profile.hbs
|
203 | <h1>{{this.displayName}}</h1>
|
204 | {{yield}}
|
205 | ```
|
206 |
|
207 | ## Customizing a Classic Component's HTML Element in JavaScript
|
208 |
|
209 | ### HTML Tag
|
210 |
|
211 | The default HTML tag name used for a component's HTML representation is `div`.
|
212 | This can be customized by setting the `tagName` property.
|
213 |
|
214 | Consider the following component class:
|
215 |
|
216 | ```app/components/emphasized-paragraph.js
|
217 | import Component from '@ember/component';
|
218 |
|
219 | export default Component.extend({
|
220 | tagName: 'em'
|
221 | });
|
222 | ```
|
223 |
|
224 | When invoked, this component would produce output that looks something like
|
225 | this:
|
226 |
|
227 | ```html
|
228 | <em id="ember1" class="ember-view"></em>
|
229 | ```
|
230 |
|
231 | ### HTML `class` Attribute
|
232 |
|
233 | The HTML `class` attribute of a component's tag can be set by providing a
|
234 | `classNames` property that is set to an array of strings:
|
235 |
|
236 | ```app/components/my-widget.js
|
237 | import Component from '@ember/component';
|
238 |
|
239 | export default Component.extend({
|
240 | classNames: ['my-class', 'my-other-class']
|
241 | });
|
242 | ```
|
243 |
|
244 | Invoking this component will produce output that looks like this:
|
245 |
|
246 | ```html
|
247 | <div id="ember1" class="ember-view my-class my-other-class"></div>
|
248 | ```
|
249 |
|
250 | `class` attribute values can also be set by providing a `classNameBindings`
|
251 | property set to an array of properties names for the component. The return
|
252 | value of these properties will be added as part of the value for the
|
253 | components's `class` attribute. These properties can be computed properties:
|
254 |
|
255 | ```app/components/my-widget.js
|
256 | import Component from '@ember/component';
|
257 | import { computed } from '@ember/object';
|
258 |
|
259 | export default Component.extend({
|
260 | classNames: ['my-class', 'my-other-class'],
|
261 | classNameBindings: ['propertyA', 'propertyB'],
|
262 |
|
263 | propertyA: 'from-a',
|
264 | propertyB: computed(function() {
|
265 | if (someLogic) { return 'from-b'; }
|
266 | })
|
267 | });
|
268 | ```
|
269 |
|
270 | Invoking this component will produce HTML that looks like:
|
271 |
|
272 | ```html
|
273 | <div id="ember1" class="ember-view my-class my-other-class from-a from-b"></div>
|
274 | ```
|
275 |
|
276 | Note that `classNames` and `classNameBindings` is in addition to the `class`
|
277 | attribute passed with the angle bracket invocation syntax. Therefore, if this
|
278 | component was invoked like so:
|
279 |
|
280 | ```handlebars
|
281 | <MyWidget class="from-invocation" />
|
282 | ```
|
283 |
|
284 | The resulting HTML will look similar to this:
|
285 |
|
286 | ```html
|
287 | <div id="ember1" class="from-invocation ember-view my-class my-other-class from-a from-b"></div>
|
288 | ```
|
289 |
|
290 | If the value of a class name binding returns a boolean the property name
|
291 | itself will be used as the class name if the property is true. The class name
|
292 | will not be added if the value is `false` or `undefined`.
|
293 |
|
294 | ```app/components/my-widget.js
|
295 | import Component from '@ember/component';
|
296 |
|
297 | export default Component.extend({
|
298 | classNameBindings: ['hovered'],
|
299 |
|
300 | hovered: true
|
301 | });
|
302 | ```
|
303 |
|
304 | Invoking this component will produce HTML that looks like:
|
305 |
|
306 | ```html
|
307 | <div id="ember1" class="ember-view hovered"></div>
|
308 | ```
|
309 |
|
310 | ### Custom Class Names for Boolean Values
|
311 |
|
312 | When using boolean class name bindings you can supply a string value other
|
313 | than the property name for use as the `class` HTML attribute by appending the
|
314 | preferred value after a ":" character when defining the binding:
|
315 |
|
316 | ```app/components/my-widget.js
|
317 | import Component from '@ember/component';
|
318 |
|
319 | export default Component.extend({
|
320 | classNameBindings: ['awesome:so-very-cool'],
|
321 |
|
322 | awesome: true
|
323 | });
|
324 | ```
|
325 |
|
326 | Invoking this component will produce HTML that looks like:
|
327 |
|
328 | ```html
|
329 | <div id="ember1" class="ember-view so-very-cool"></div>
|
330 | ```
|
331 |
|
332 | Boolean value class name bindings whose property names are in a
|
333 | camelCase-style format will be converted to a dasherized format:
|
334 |
|
335 | ```app/components/my-widget.js
|
336 | import Component from '@ember/component';
|
337 |
|
338 | export default Component.extend({
|
339 | classNameBindings: ['isUrgent'],
|
340 |
|
341 | isUrgent: true
|
342 | });
|
343 | ```
|
344 |
|
345 | Invoking this component will produce HTML that looks like:
|
346 |
|
347 | ```html
|
348 | <div id="ember1" class="ember-view is-urgent"></div>
|
349 | ```
|
350 |
|
351 | Class name bindings can also refer to object values that are found by
|
352 | traversing a path relative to the component itself:
|
353 |
|
354 | ```app/components/my-widget.js
|
355 | import Component from '@ember/component';
|
356 | import EmberObject from '@ember/object';
|
357 |
|
358 | export default Component.extend({
|
359 | classNameBindings: ['messages.empty'],
|
360 |
|
361 | messages: EmberObject.create({
|
362 | empty: true
|
363 | })
|
364 | });
|
365 | ```
|
366 |
|
367 | Invoking this component will produce HTML that looks like:
|
368 |
|
369 | ```html
|
370 | <div id="ember1" class="ember-view empty"></div>
|
371 | ```
|
372 |
|
373 | If you want to add a class name for a property which evaluates to true and and
|
374 | a different class name if it evaluates to false, you can pass a binding like
|
375 | this:
|
376 |
|
377 | ```app/components/my-widget.js
|
378 | import Component from '@ember/component';
|
379 |
|
380 | export default Component.extend({
|
381 | classNameBindings: ['isEnabled:enabled:disabled'],
|
382 | isEnabled: true
|
383 | });
|
384 | ```
|
385 |
|
386 | Invoking this component will produce HTML that looks like:
|
387 |
|
388 | ```html
|
389 | <div id="ember1" class="ember-view enabled"></div>
|
390 | ```
|
391 |
|
392 | When isEnabled is `false`, the resulting HTML representation looks like this:
|
393 |
|
394 | ```html
|
395 | <div id="ember1" class="ember-view disabled"></div>
|
396 | ```
|
397 |
|
398 | This syntax offers the convenience to add a class if a property is `false`:
|
399 |
|
400 | ```app/components/my-widget.js
|
401 | import Component from '@ember/component';
|
402 |
|
403 | // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false
|
404 | export default Component.extend({
|
405 | classNameBindings: ['isEnabled::disabled'],
|
406 | isEnabled: true
|
407 | });
|
408 | ```
|
409 |
|
410 | Invoking this component when the `isEnabled` property is true will produce
|
411 | HTML that looks like:
|
412 |
|
413 | ```html
|
414 | <div id="ember1" class="ember-view"></div>
|
415 | ```
|
416 |
|
417 | Invoking it when the `isEnabled` property on the component is `false` will
|
418 | produce HTML that looks like:
|
419 |
|
420 | ```html
|
421 | <div id="ember1" class="ember-view disabled"></div>
|
422 | ```
|
423 |
|
424 | Updates to the value of a class name binding will result in automatic update
|
425 | of the HTML `class` attribute in the component's rendered HTML
|
426 | representation. If the value becomes `false` or `undefined` the class name
|
427 | will be removed.
|
428 |
|
429 | Both `classNames` and `classNameBindings` are concatenated properties. See
|
430 | [EmberObject](/ember/release/classes/EmberObject) documentation for more
|
431 | information about concatenated properties.
|
432 |
|
433 | ### Other HTML Attributes
|
434 |
|
435 | The HTML attribute section of a component's tag can be set by providing an
|
436 | `attributeBindings` property set to an array of property names on the
|
437 | component. The return value of these properties will be used as the value of
|
438 | the component's HTML associated attribute:
|
439 |
|
440 | ```app/components/my-anchor.js
|
441 | import Component from '@ember/component';
|
442 |
|
443 | export default Component.extend({
|
444 | tagName: 'a',
|
445 | attributeBindings: ['href'],
|
446 |
|
447 | href: 'http://google.com'
|
448 | });
|
449 | ```
|
450 |
|
451 | Invoking this component will produce HTML that looks like:
|
452 |
|
453 | ```html
|
454 | <a id="ember1" class="ember-view" href="http://google.com"></a>
|
455 | ```
|
456 |
|
457 | One property can be mapped on to another by placing a ":" between the source
|
458 | property and the destination property:
|
459 |
|
460 | ```app/components/my-anchor.js
|
461 | import Component from '@ember/component';
|
462 |
|
463 | export default Component.extend({
|
464 | tagName: 'a',
|
465 | attributeBindings: ['url:href'],
|
466 |
|
467 | url: 'http://google.com'
|
468 | });
|
469 | ```
|
470 |
|
471 | Invoking this component will produce HTML that looks like:
|
472 |
|
473 | ```html
|
474 | <a id="ember1" class="ember-view" href="http://google.com"></a>
|
475 | ```
|
476 |
|
477 | HTML attributes passed with angle bracket invocations will take precedence
|
478 | over those specified in `attributeBindings`. Therefore, if this component was
|
479 | invoked like so:
|
480 |
|
481 | ```handlebars
|
482 | <MyAnchor href="http://bing.com" @url="http://google.com" />
|
483 | ```
|
484 |
|
485 | The resulting HTML will looks like this:
|
486 |
|
487 | ```html
|
488 | <a id="ember1" class="ember-view" href="http://bing.com"></a>
|
489 | ```
|
490 |
|
491 | Note that the `href` attribute is ultimately set to `http://bing.com`, despite
|
492 | it having attribute binidng to the `url` property, which was set to
|
493 | `http://google.com`.
|
494 |
|
495 | Namespaced attributes (e.g. `xlink:href`) are supported, but have to be
|
496 | mapped, since `:` is not a valid character for properties in Javascript:
|
497 |
|
498 | ```app/components/my-use.js
|
499 | import Component from '@ember/component';
|
500 |
|
501 | export default Component.extend({
|
502 | tagName: 'use',
|
503 | attributeBindings: ['xlinkHref:xlink:href'],
|
504 |
|
505 | xlinkHref: '#triangle'
|
506 | });
|
507 | ```
|
508 |
|
509 | Invoking this component will produce HTML that looks like:
|
510 |
|
511 | ```html
|
512 | <use xlink:href="#triangle"></use>
|
513 | ```
|
514 |
|
515 | If the value of a property monitored by `attributeBindings` is a boolean, the
|
516 | attribute will be present or absent depending on the value:
|
517 |
|
518 | ```app/components/my-text-input.js
|
519 | import Component from '@ember/component';
|
520 |
|
521 | export default Component.extend({
|
522 | tagName: 'input',
|
523 | attributeBindings: ['disabled'],
|
524 |
|
525 | disabled: false
|
526 | });
|
527 | ```
|
528 |
|
529 | Invoking this component will produce HTML that looks like:
|
530 |
|
531 | ```html
|
532 | <input id="ember1" class="ember-view" />
|
533 | ```
|
534 |
|
535 | `attributeBindings` can refer to computed properties:
|
536 |
|
537 | ```app/components/my-text-input.js
|
538 | import Component from '@ember/component';
|
539 | import { computed } from '@ember/object';
|
540 |
|
541 | export default Component.extend({
|
542 | tagName: 'input',
|
543 | attributeBindings: ['disabled'],
|
544 |
|
545 | disabled: computed(function() {
|
546 | if (someLogic) {
|
547 | return true;
|
548 | } else {
|
549 | return false;
|
550 | }
|
551 | })
|
552 | });
|
553 | ```
|
554 |
|
555 | To prevent setting an attribute altogether, use `null` or `undefined` as the
|
556 | value of the property used in `attributeBindings`:
|
557 |
|
558 | ```app/components/my-text-input.js
|
559 | import Component from '@ember/component';
|
560 |
|
561 | export default Component.extend({
|
562 | tagName: 'form',
|
563 | attributeBindings: ['novalidate'],
|
564 | novalidate: null
|
565 | });
|
566 | ```
|
567 |
|
568 | Updates to the property of an attribute binding will result in automatic
|
569 | update of the HTML attribute in the component's HTML output.
|
570 |
|
571 | `attributeBindings` is a concatenated property. See
|
572 | [EmberObject](/ember/release/classes/EmberObject) documentation for more
|
573 | information about concatenated properties.
|
574 |
|
575 | ## Layouts
|
576 |
|
577 | The `layout` property can be used to dynamically specify a template associated
|
578 | with a component class, instead of relying on Ember to link together a
|
579 | component class and a template based on file names.
|
580 |
|
581 | In general, applications should not use this feature, but it's commonly used
|
582 | in addons for historical reasons.
|
583 |
|
584 | The `layout` property should be set to the default export of a template
|
585 | module, which is the name of a template file without the `.hbs` extension.
|
586 |
|
587 | ```app/templates/components/person-profile.hbs
|
588 | <h1>Person's Title</h1>
|
589 | <div class='details'>{{yield}}</div>
|
590 | ```
|
591 |
|
592 | ```app/components/person-profile.js
|
593 | import Component from '@ember/component';
|
594 | import layout from '../templates/components/person-profile';
|
595 |
|
596 | export default Component.extend({
|
597 | layout
|
598 | });
|
599 | ```
|
600 |
|
601 | If you invoke the component:
|
602 |
|
603 | ```handlebars
|
604 | <PersonProfile>
|
605 | <h2>Chief Basket Weaver</h2>
|
606 | <h3>Fisherman Industries</h3>
|
607 | </PersonProfile>
|
608 | ```
|
609 |
|
610 | or
|
611 |
|
612 | ```handlebars
|
613 | {{#person-profile}}
|
614 | <h2>Chief Basket Weaver</h2>
|
615 | <h3>Fisherman Industries</h3>
|
616 | {{/person-profile}}
|
617 | ```
|
618 |
|
619 | It will result in the following HTML output:
|
620 |
|
621 | ```html
|
622 | <h1>Person's Title</h1>
|
623 | <div class="details">
|
624 | <h2>Chief Basket Weaver</h2>
|
625 | <h3>Fisherman Industries</h3>
|
626 | </div>
|
627 | ```
|
628 |
|
629 | ## Handling Browser Events
|
630 |
|
631 | There are two ways to handle user-initiated events:
|
632 |
|
633 | ### Using the `on` modifier to capture browser events
|
634 |
|
635 | In a component's template, you can attach an event handler to any element with the `on` modifier:
|
636 |
|
637 | ```handlebars
|
638 | <button {{on 'click' this.doSomething}} />
|
639 | ```
|
640 |
|
641 | This will call the function on your component:
|
642 |
|
643 | ```js
|
644 | import Component from '@ember/component';
|
645 |
|
646 | export default class ExampleComponent extends Component {
|
647 | doSomething = (event) => {
|
648 | // `event` is the native click Event
|
649 | console.log('clicked on the button');
|
650 | };
|
651 | });
|
652 | ```
|
653 |
|
654 | See the [Guide on Component event
|
655 | handlers](https://guides.emberjs.com/release/components/component-state-and-actions/#toc_html-modifiers-and-actions)
|
656 | and the [API docs for `on`](../Ember.Templates.helpers/methods/on?anchor=on)
|
657 | for more details.
|
658 |
|
659 | ### Event Handler Methods
|
660 |
|
661 | Components can also respond to user-initiated events by implementing a method
|
662 | that matches the event name. This approach is appropriate when the same event
|
663 | should be handled by all instances of the same component.
|
664 |
|
665 | An event object will be passed as the argument to the event handler method.
|
666 |
|
667 | ```app/components/my-widget.js
|
668 | import Component from '@ember/component';
|
669 |
|
670 | export default Component.extend({
|
671 | click(event) {
|
672 | // `event.target` is either the component's element or one of its children
|
673 | let tag = event.target.tagName.toLowerCase();
|
674 | console.log('clicked on a `<${tag}>` HTML element!');
|
675 | }
|
676 | });
|
677 | ```
|
678 |
|
679 | In this example, whenever the user clicked anywhere inside the component, it
|
680 | will log a message to the console.
|
681 |
|
682 | It is possible to handle event types other than `click` by implementing the
|
683 | following event handler methods. In addition, custom events can be registered
|
684 | by using `Application.customEvents`.
|
685 |
|
686 | Touch events:
|
687 |
|
688 | * `touchStart`
|
689 | * `touchMove`
|
690 | * `touchEnd`
|
691 | * `touchCancel`
|
692 |
|
693 | Keyboard events:
|
694 |
|
695 | * `keyDown`
|
696 | * `keyUp`
|
697 | * `keyPress`
|
698 |
|
699 | Mouse events:
|
700 |
|
701 | * `mouseDown`
|
702 | * `mouseUp`
|
703 | * `contextMenu`
|
704 | * `click`
|
705 | * `doubleClick`
|
706 | * `focusIn`
|
707 | * `focusOut`
|
708 |
|
709 | Form events:
|
710 |
|
711 | * `submit`
|
712 | * `change`
|
713 | * `focusIn`
|
714 | * `focusOut`
|
715 | * `input`
|
716 |
|
717 | Drag and drop events:
|
718 |
|
719 | * `dragStart`
|
720 | * `drag`
|
721 | * `dragEnter`
|
722 | * `dragLeave`
|
723 | * `dragOver`
|
724 | * `dragEnd`
|
725 | * `drop`
|
726 |
|
727 | @class Component
|
728 | @extends Ember.CoreView
|
729 | @uses Ember.TargetActionSupport
|
730 | @uses Ember.ClassNamesSupport
|
731 | @uses Ember.ActionSupport
|
732 | @uses Ember.ViewMixin
|
733 | @uses Ember.ViewStateSupport
|
734 | @public
|
735 | */
|
736 | interface Component<S = unknown>
|
737 | extends CoreView,
|
738 | ChildViewsSupport,
|
739 | ViewStateSupport,
|
740 | ClassNamesSupport,
|
741 | TargetActionSupport,
|
742 | ActionSupport,
|
743 | ViewMixin,
|
744 | ComponentMethods {}
|
745 | const Component_base: Readonly<typeof CoreView> &
|
746 | (new (owner?: import('@ember/-internals/owner').default | undefined) => CoreView) &
|
747 | import('@ember/object/mixin').default &
|
748 | ComponentMethods;
|
749 | class Component<S = unknown> extends Component_base implements PropertyDidChange {
|
750 | isComponent: boolean;
|
751 | private [SIGNATURE];
|
752 | _superRerender: ViewMixin['rerender'];
|
753 | [IS_DISPATCHING_ATTRS]: boolean;
|
754 | [DIRTY_TAG]: DirtyableTag;
|
755 | init(properties?: object | undefined): void;
|
756 | __dispatcher?: EventDispatcher | null;
|
757 | get _dispatcher(): EventDispatcher | null;
|
758 | on<Target>(
|
759 | name: string,
|
760 | target: Target,
|
761 | method: string | ((this: Target, ...args: any[]) => void)
|
762 | ): this;
|
763 | on(name: string, method: ((...args: any[]) => void) | string): this;
|
764 | _rerender(): void;
|
765 | [PROPERTY_DID_CHANGE](key: string, value?: unknown): void;
|
766 | getAttr(key: string): unknown;
|
767 | /**
|
768 | Normally, Ember's component model is "write-only". The component takes a
|
769 | bunch of attributes that it got passed in, and uses them to render its
|
770 | template.
|
771 |
|
772 | One nice thing about this model is that if you try to set a value to the
|
773 | same thing as last time, Ember (through HTMLBars) will avoid doing any
|
774 | work on the DOM.
|
775 |
|
776 | This is not just a performance optimization. If an attribute has not
|
777 | changed, it is important not to clobber the element's "hidden state".
|
778 | For example, if you set an input's `value` to the same value as before,
|
779 | it will clobber selection state and cursor position. In other words,
|
780 | setting an attribute is not **always** idempotent.
|
781 |
|
782 | This method provides a way to read an element's attribute and also
|
783 | update the last value Ember knows about at the same time. This makes
|
784 | setting an attribute idempotent.
|
785 |
|
786 | In particular, what this means is that if you get an `<input>` element's
|
787 | `value` attribute and then re-render the template with the same value,
|
788 | it will avoid clobbering the cursor and selection position.
|
789 | Since most attribute sets are idempotent in the browser, you typically
|
790 | can get away with reading attributes using jQuery, but the most reliable
|
791 | way to do so is through this method.
|
792 | @method readDOMAttr
|
793 |
|
794 | @param {String} name the name of the attribute
|
795 | @return String
|
796 | @public
|
797 | */
|
798 | readDOMAttr(name: string): any;
|
799 | attributeBindings?: string[];
|
800 | /**
|
801 | Enables components to take a list of parameters as arguments.
|
802 | For example, a component that takes two parameters with the names
|
803 | `name` and `age`:
|
804 |
|
805 | ```app/components/my-component.js
|
806 | import Component from '@ember/component';
|
807 |
|
808 | let MyComponent = Component.extend();
|
809 |
|
810 | MyComponent.reopenClass({
|
811 | positionalParams: ['name', 'age']
|
812 | });
|
813 |
|
814 | export default MyComponent;
|
815 | ```
|
816 |
|
817 | It can then be invoked like this:
|
818 |
|
819 | ```hbs
|
820 | {{my-component "John" 38}}
|
821 | ```
|
822 |
|
823 | The parameters can be referred to just like named parameters:
|
824 |
|
825 | ```hbs
|
826 | Name: {{name}}, Age: {{age}}.
|
827 | ```
|
828 |
|
829 | Using a string instead of an array allows for an arbitrary number of
|
830 | parameters:
|
831 |
|
832 | ```app/components/my-component.js
|
833 | import Component from '@ember/component';
|
834 |
|
835 | let MyComponent = Component.extend();
|
836 |
|
837 | MyComponent.reopenClass({
|
838 | positionalParams: 'names'
|
839 | });
|
840 |
|
841 | export default MyComponent;
|
842 | ```
|
843 |
|
844 | It can then be invoked like this:
|
845 |
|
846 | ```hbs
|
847 | {{my-component "John" "Michael" "Scott"}}
|
848 | ```
|
849 | The parameters can then be referred to by enumerating over the list:
|
850 |
|
851 | ```hbs
|
852 | {{#each names as |name|}}{{name}}{{/each}}
|
853 | ```
|
854 |
|
855 | @static
|
856 | @public
|
857 | @property positionalParams
|
858 | @since 1.13.0
|
859 | */ /**
|
860 | Enables components to take a list of parameters as arguments.
|
861 | For example, a component that takes two parameters with the names
|
862 | `name` and `age`:
|
863 |
|
864 | ```app/components/my-component.js
|
865 | import Component from '@ember/component';
|
866 |
|
867 | let MyComponent = Component.extend();
|
868 |
|
869 | MyComponent.reopenClass({
|
870 | positionalParams: ['name', 'age']
|
871 | });
|
872 |
|
873 | export default MyComponent;
|
874 | ```
|
875 |
|
876 | It can then be invoked like this:
|
877 |
|
878 | ```hbs
|
879 | {{my-component "John" 38}}
|
880 | ```
|
881 |
|
882 | The parameters can be referred to just like named parameters:
|
883 |
|
884 | ```hbs
|
885 | Name: {{name}}, Age: {{age}}.
|
886 | ```
|
887 |
|
888 | Using a string instead of an array allows for an arbitrary number of
|
889 | parameters:
|
890 |
|
891 | ```app/components/my-component.js
|
892 | import Component from '@ember/component';
|
893 |
|
894 | let MyComponent = Component.extend();
|
895 |
|
896 | MyComponent.reopenClass({
|
897 | positionalParams: 'names'
|
898 | });
|
899 |
|
900 | export default MyComponent;
|
901 | ```
|
902 |
|
903 | It can then be invoked like this:
|
904 |
|
905 | ```hbs
|
906 | {{my-component "John" "Michael" "Scott"}}
|
907 | ```
|
908 | The parameters can then be referred to by enumerating over the list:
|
909 |
|
910 | ```hbs
|
911 | {{#each names as |name|}}{{name}}{{/each}}
|
912 | ```
|
913 |
|
914 | @static
|
915 | @public
|
916 | @property positionalParams
|
917 | @since 1.13.0
|
918 | */
|
919 | static positionalParams: string | string[];
|
920 | /**
|
921 | Layout can be used to wrap content in a component.
|
922 | @property layout
|
923 | @type Function
|
924 | @public
|
925 | */
|
926 | layout?: TemplateFactory | Template;
|
927 | /**
|
928 | The name of the layout to lookup if no layout is provided.
|
929 | By default `Component` will lookup a template with this name in
|
930 | `Ember.TEMPLATES` (a shared global object).
|
931 | @property layoutName
|
932 | @type String
|
933 | @default undefined
|
934 | @private
|
935 | */
|
936 | layoutName?: string;
|
937 | /**
|
938 | The WAI-ARIA role of the control represented by this view. For example, a
|
939 | button may have a role of type 'button', or a pane may have a role of
|
940 | type 'alertdialog'. This property is used by assistive software to help
|
941 | visually challenged users navigate rich web applications.
|
942 |
|
943 | The full list of valid WAI-ARIA roles is available at:
|
944 | [https://www.w3.org/TR/wai-aria/#roles_categorization](https://www.w3.org/TR/wai-aria/#roles_categorization)
|
945 |
|
946 | @property ariaRole
|
947 | @type String
|
948 | @default undefined
|
949 | @public
|
950 | */
|
951 | ariaRole?: string;
|
952 | static isComponentFactory: boolean;
|
953 | static toString(): string;
|
954 | }
|
955 | export default Component;
|
956 | }
|
957 |
|
\ | No newline at end of file |