@@ -129,8 +129,8 @@ The generator has to rely on some guidance from the user to mark classes that
129
129
injector has to instantiate. There are two ways of doing this: @Injectables
130
130
or custom class annotation.
131
131
132
- ` @Injectables ` is an annotation provided by the di package which can be
133
- applied on a library definition with a list of types that the generator
132
+ ` @Injectables ` is an annotation provided by the di package which can be
133
+ applied on a library definition with a list of types that the generator
134
134
should process.
135
135
136
136
```
@@ -146,12 +146,11 @@ class MyService {
146
146
}
147
147
```
148
148
149
- @Injectables annotation should be mainly used with classes that are out of
150
- your control (ex. you can't modify the source code -- third party library).
149
+ ` @Injectables ` annotation should be mainly used with classes that are out of
150
+ your control (ex. you can't modify the source code -- third party library).
151
151
In all other cases it's preferable to use custom class annotation(s).
152
152
153
- You can also define your own custom class annotations and apply them on
154
- classes that you need to be instantiated by the injector.
153
+ You can define your own custom class annotations
155
154
156
155
```
157
156
library injectable;
@@ -165,18 +164,20 @@ class InjectableService {
165
164
}
166
165
```
167
166
167
+ and apply them on classes that you need to be instantiated by the injector.
168
+
168
169
```
169
170
@InjectableService()
170
171
class QueryService {
171
172
// ...
172
173
}
173
174
```
174
175
175
- You can then then configure generator with those annotations.
176
+ You can then then configure generator to look for those annotations.
176
177
177
- When configuring the generator with the custom annotation you need to pass
178
- a fully qualified class name (including the library prefix). In case of the
179
- above example the fully qualified name of Service annotation would be
178
+ When configuring the generator with the custom annotation you need to pass
179
+ a fully qualified class name (including the library prefix). In case of the
180
+ above example the fully qualified name of Service annotation would be
180
181
` injectable.InjectableService ` .
181
182
182
183
## AngularDart Parser Generator
@@ -186,6 +187,67 @@ and then compiles them into Dart, so at runtime it doesn't have to parse those
186
187
expressions and while invoking the expressions it uses pre-generated code to
187
188
access fields and methods, so it doesn't have to use mirrors.
188
189
190
+ There are many places in the application where expressions can be used:
191
+
192
+ 1 . HTML template attributes
193
+ 1 . mustaches {{ }} (technically a directive)
194
+ 1 . custom syntax directives like ng-repeat
195
+ 1 . component/directive attribute mappings
196
+ 1 . programmatic calls to Scope.$eval, Scope.$watch/$watchCollection,
197
+ Parser.call, etc.
198
+
199
+ It's not always trivial to tell if element attribute in HTML template contains
200
+ an expression or just a string value.
201
+
202
+ Expression extractor has to:
203
+
204
+ 1 . find all component/directive definitions in the source code and extract
205
+ their metadata (NgAnnotations, field attribute mapping annotations)
206
+ 1 . statically "compile" all the templates to identify all directives and
207
+ extract all attributes and mustaches that contain expressions
208
+
209
+ Sometimes directives with attributes mapped with @ spec can subsequently call
210
+ ` Scope.$eval ` on the string value of the attribute. In those cases directive
211
+ can tell expression extractor that attribute value is used in this way via
212
+ ` exportExpressionAttrs ` property on ` NgDirective ` /` NgComponent ` annotation. Ex:
213
+
214
+ ```
215
+ @NgComponent(
216
+ selector: 'foo',
217
+ map: const {
218
+ 'bar': '@bar'
219
+ },
220
+ exportExpressionAttrs: 'bar'
221
+ )
222
+ class FooComponent implement NgAttachAware {
223
+ String bar;
224
+ Scope scope;
225
+
226
+ FooComponent(Scope this.scope);
227
+
228
+ attach() {
229
+ scope.$watch(bar, _barChanged);
230
+ }
231
+
232
+ _barChanged(val) {}
233
+ }
234
+ ```
235
+
236
+ Similarly, if directive programmatically evaluates an expression it can tell
237
+ expression extractor which expressions it evaluates:
238
+
239
+ ```
240
+ @NgDirective(
241
+ selector: 'foo'
242
+ exportExpressions: '1 + 3'
243
+ )
244
+ class FooDirective {
245
+ FooComponent(Scope scope) {
246
+ _showResult(scope.$eval('1 + 2'));
247
+ }
248
+ }
249
+ ```
250
+
189
251
You can find an example of how to use the parser generator in
190
252
` bin/generator.dart ` file.
191
253
0 commit comments