/
index.ts
326 lines (256 loc) · 8.55 KB
/
index.ts
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
/**
[Glimmer](https://github.com/tildeio/glimmer) is a templating engine used by Ember.js that is compatible with a subset of the [Handlebars](http://handlebarsjs.com/) syntax.
### Showing a property
Templates manage the flow of an application's UI, and display state (through
the DOM) to a user. For example, given a component with the property "name",
that component's template can use the name in several ways:
```app/components/person-profile.js
import Component from '@ember/component';
export default Component.extend({
name: 'Jill'
});
```
```app/components/person-profile.hbs
{{this.name}}
<div>{{this.name}}</div>
<span data-name={{this.name}}></span>
```
Any time the "name" property on the component changes, the DOM will be
updated.
Properties can be chained as well:
```handlebars
{{@aUserModel.name}}
<div>{{@listOfUsers.firstObject.name}}</div>
```
### Using Ember helpers
When content is passed in mustaches `{{}}`, Ember will first try to find a helper
or component with that name. For example, the `if` helper:
```app/components/person-profile.hbs
{{if this.name "I have a name" "I have no name"}}
<span data-has-name={{if this.name true}}></span>
```
The returned value is placed where the `{{}}` is called. The above style is
called "inline". A second style of helper usage is called "block". For example:
```handlebars
{{#if this.name}}
I have a name
{{else}}
I have no name
{{/if}}
```
The block form of helpers allows you to control how the UI is created based
on the values of properties.
A third form of helper is called "nested". For example here the concat
helper will add " Doe" to a displayed name if the person has no last name:
```handlebars
<span data-name={{concat this.firstName (
if this.lastName (concat " " this.lastName) "Doe"
)}}></span>
```
Ember's built-in helpers are described under the [Ember.Templates.helpers](/ember/release/classes/Ember.Templates.helpers)
namespace. Documentation on creating custom helpers can be found under
[helper](/ember/release/functions/@ember%2Fcomponent%2Fhelper/helper) (or
under [Helper](/ember/release/classes/Helper) if a helper requires access to
dependency injection).
### Invoking a Component
Ember components represent state to the UI of an application. Further
reading on components can be found under [Component](/ember/release/classes/Component).
@module @ember/component
@main @ember/component
@public
*/
/**
@module ember
*/
/**
@class Ember.Templates.helpers
@public
*/
/**
`{{yield}}` denotes an area of a template that will be rendered inside
of another template.
### Use with `Component`
When designing components `{{yield}}` is used to denote where, inside the component's
template, an optional block passed to the component should render:
```app/templates/application.hbs
<LabeledTextfield @value={{@model.name}}>
First name:
</LabeledTextfield>
```
```app/components/labeled-textfield.hbs
<label>
{{yield}} <Input @value={{@value}} />
</label>
```
Result:
```html
<label>
First name: <input type="text" />
</label>
```
Additionally you can `yield` properties into the context for use by the consumer:
```app/templates/application.hbs
<LabeledTextfield @value={{@model.validation}} @validator={{this.firstNameValidator}} as |validationError|>
{{#if validationError}}
<p class="error">{{validationError}}</p>
{{/if}}
First name:
</LabeledTextfield>
```
```app/components/labeled-textfield.hbs
<label>
{{yield this.validationError}} <Input @value={{@value}} />
</label>
```
Result:
```html
<label>
<p class="error">First Name must be at least 3 characters long.</p>
First name: <input type="text" />
</label>
```
@method yield
@for Ember.Templates.helpers
@param {Hash} options
@return {String} HTML string
@public
*/
/**
`{{(has-block)}}` indicates if the component was invoked with a block.
This component is invoked with a block:
```handlebars
{{#my-component}}
Hi Jen!
{{/my-component}}
```
This component is invoked without a block:
```handlebars
{{my-component}}
```
Using angle bracket invocation, this looks like:
```html
<MyComponent>Hi Jen!</MyComponent> {{! with a block}}
```
```html
<MyComponent/> {{! without a block}}
```
This is useful when you want to create a component that can optionally take a block
and then render a default template when it is not invoked with a block.
```app/templates/components/my-component.hbs
{{#if (has-block)}}
Welcome {{yield}}, we are happy you're here!
{{else}}
Hey you! You're great!
{{/if}}
```
@method has-block
@for Ember.Templates.helpers
@param {String} the name of the block. The name (at the moment) is either "main" or "inverse" (though only curly components support inverse)
@return {Boolean} `true` if the component was invoked with a block
@public
*/
/**
`{{(has-block-params)}}` indicates if the component was invoked with block params.
This component is invoked with block params:
```handlebars
{{#my-component as |favoriteFlavor|}}
Hi Jen!
{{/my-component}}
```
This component is invoked without block params:
```handlebars
{{#my-component}}
Hi Jenn!
{{/my-component}}
```
With angle bracket syntax, block params look like this:
```handlebars
<MyComponent as |favoriteFlavor|>
Hi Jen!
</MyComponent>
```
And without block params:
```handlebars
<MyComponent>
Hi Jen!
</MyComponent>
```
This is useful when you want to create a component that can render itself
differently when it is not invoked with block params.
```app/templates/components/my-component.hbs
{{#if (has-block-params)}}
Welcome {{yield this.favoriteFlavor}}, we're happy you're here and hope you
enjoy your favorite ice cream flavor.
{{else}}
Welcome {{yield}}, we're happy you're here, but we're unsure what
flavor ice cream you would enjoy.
{{/if}}
```
@method has-block-params
@for Ember.Templates.helpers
@param {String} the name of the block. The name (at the moment) is either "main" or "inverse" (though only curly components support inverse)
@return {Boolean} `true` if the component was invoked with block params
@public
*/
/**
Execute the `debugger` statement in the current template's context.
```handlebars
{{debugger}}
```
When using the debugger helper you will have access to a `get` function. This
function retrieves values available in the context of the template.
For example, if you're wondering why a value `{{foo}}` isn't rendering as
expected within a template, you could place a `{{debugger}}` statement and,
when the `debugger;` breakpoint is hit, you can attempt to retrieve this value:
```
> get('foo')
```
`get` is also aware of keywords. So in this situation
```handlebars
{{#each this.items as |item|}}
{{debugger}}
{{/each}}
```
You'll be able to get values from the current item:
```
> get('item.name')
```
You can also access the context of the view to make sure it is the object that
you expect:
```
> context
```
@method debugger
@for Ember.Templates.helpers
@public
*/
export { templateFactory as template, templateCacheCounters } from '@glimmer/opcode-compiler';
export { default as RootTemplate } from './lib/templates/root';
export { default as Input } from './lib/components/input';
export { default as LinkTo } from './lib/components/link-to';
export { default as Textarea } from './lib/components/textarea';
export { default as Component } from './lib/component';
export { default as Helper, helper } from './lib/helper';
export { SafeString, escapeExpression, htmlSafe, isHTMLSafe } from './lib/utils/string';
export { Renderer, _resetRenderers, renderSettled } from './lib/renderer';
export {
getTemplate,
setTemplate,
hasTemplate,
getTemplates,
setTemplates,
} from './lib/template_registry';
export { setupEngineRegistry, setupApplicationRegistry } from './lib/setup-registry';
export { DOMChanges, NodeDOMTreeConstruction, DOMTreeConstruction } from './lib/dom';
// needed for test
// TODO just test these through public API
// a lot of these are testing how a problem was solved
// rather than the problem was solved
export { default as OutletView } from './lib/views/outlet';
export { OutletState } from './lib/utils/outlet';
export {
componentCapabilities,
modifierCapabilities,
setComponentManager,
} from './lib/utils/managers';
export { isSerializationFirstNode } from './lib/utils/serialization-first-node-helpers';