1+ <!doctype html>
2+ < html >
3+ < head >
4+ < meta charset ="utf-8 " />
5+
6+ < title >
7+ Constructor vs. Property QueryList Injection In Angular 2 Beta 8
8+ </ title >
9+
10+ < link rel ="stylesheet " type ="text/css " href ="./demo.css "> </ link >
11+ </ head >
12+ < body >
13+
14+ < h1 >
15+ Constructor vs. Property QueryList Injection In Angular 2 Beta 8
16+ </ h1 >
17+
18+ < my-app >
19+ Loading...
20+ </ my-app >
21+
22+ <!-- Load demo scripts. -->
23+ < script type ="text/javascript " src ="../../vendor/angularjs-2-beta/8/es6-shim.min.js "> </ script >
24+ < script type ="text/javascript " src ="../../vendor/angularjs-2-beta/8/Rx.umd.min.js "> </ script >
25+ < script type ="text/javascript " src ="../../vendor/angularjs-2-beta/8/angular2-polyfills.min.js "> </ script >
26+ < script type ="text/javascript " src ="../../vendor/angularjs-2-beta/8/angular2-all.umd.js "> </ script >
27+ <!-- AlmondJS - minimal implementation of RequireJS. -->
28+ < script type ="text/javascript " src ="../../vendor/angularjs-2-beta/8/almond.js "> </ script >
29+ < script type ="text/javascript ">
30+
31+ // Defer bootstrapping until all of the components have been declared.
32+ // --
33+ // NOTE: Not all components have to be required here since they will be
34+ // implicitly required by other components.
35+ requirejs (
36+ [ /* Using require() for better readability. */ ] ,
37+ function run ( ) {
38+
39+ var App = require ( "App" ) ;
40+
41+ ng . platform . browser . bootstrap ( App ) ;
42+
43+ }
44+ ) ;
45+
46+
47+ // --------------------------------------------------------------------------- //
48+ // --------------------------------------------------------------------------- //
49+
50+
51+ // I provide the root App component.
52+ define (
53+ "App" ,
54+ function registerApp ( ) {
55+
56+ var ItemA = require ( "ItemA" ) ;
57+ var ItemB = require ( "ItemB" ) ;
58+
59+ // Configure the App component definition.
60+ ng . core
61+ . Component ( {
62+ selector : "my-app" ,
63+ directives : [ ItemA , ItemB ] ,
64+
65+ // Here, we are asking Angular to inject a query list for the
66+ // collection of ItemA components rendered within our component
67+ // view. This will inject `itemAList` as a public property on
68+ // the App component instance.
69+ // --
70+ // CAUTION: View queries are set before the ngAfterViewInit()
71+ // life-cycle method is called, but after the ngOnInit() life-
72+ // cycle method is called. As such, the `itemAList` property will
73+ // not exist until the View is initialized.
74+ queries : {
75+ itemAList : new ng . core . ViewChildren ( ItemA )
76+ } ,
77+
78+ // Notice that our view has two different sets of components -
79+ // ItemA and ItemB instances. Each of these will be monitored
80+ // using a different live query.
81+ template :
82+ `
83+ <item-a></item-a>
84+ <item-a></item-a>
85+ <br />
86+ <item-b></item-b>
87+ <item-b></item-b>
88+ <item-b></item-b>
89+
90+ <div *ngIf="showMore">
91+ <item-a></item-a>
92+ <item-b></item-b>
93+ </div>
94+ `
95+ } )
96+ . Class ( {
97+ constructor : AppController ,
98+
99+ // Define life-cycle methods on the prototype so that they are
100+ // picked up at runtime.
101+ ngOnInit : function noop ( ) { } ,
102+ ngAfterViewInit : function noop ( ) { }
103+ } )
104+ ;
105+
106+ // Here, we're asking Angular to inject a live query of the ItemB view
107+ // children as a constructor argument for the component instance. Just
108+ // like the live query defined in the component meta-data, this one will
109+ // not contain items until the view has been initialized. However, unlike
110+ // the other live query, we can at least reference this variable before
111+ // the view has been initialized (where we can subscribe to the changes).
112+ AppController . parameters = [
113+ [
114+ new ng . core . Inject ( ng . core . ViewChildren ) ,
115+ new ng . core . ViewChildren ( ItemB )
116+ ]
117+ ] ;
118+
119+ return ( AppController ) ;
120+
121+
122+ // I control the App component.
123+ function AppController ( itemBList ) {
124+
125+ var vm = this ;
126+
127+ // I determine if we are showing the extra components.
128+ vm . showMore = false ;
129+
130+ // The ViewChildren construct is a live query of the components in
131+ // the view. So, in order to see how this live query changes over
132+ // time, we're going to reveal more components after a short delay.
133+ setTimeout (
134+ function revealMore ( ) {
135+
136+ console . info ( "- - - - Reveal More Components - - - -" ) ;
137+ vm . showMore = true ;
138+
139+ } ,
140+ ( 5 * 1000 )
141+ ) ;
142+
143+ // While the itemBList was provided via constructor injection, the
144+ // view still has not yet been initialized. As such, this list will
145+ // be empty. But, since we have a reference to it, we can subscribe
146+ // to changes (that will be triggered after the view is initialized).
147+ itemBList . changes . subscribe (
148+ function handleValue ( queryList ) {
149+
150+ console . warn ( "itemBList Change Detection (constructor)" ) ;
151+ console . log ( "itemBList:" , itemBList . length ) ;
152+
153+ }
154+ ) ;
155+
156+ // Expose the public methods.
157+ vm . ngAfterViewInit = ngAfterViewInit ;
158+ vm . ngOnInit = ngOnInit ;
159+
160+
161+ // ---
162+ // PUBLIC METHODS.
163+ // ---
164+
165+
166+ // I get called once after the component's view has been initialized.
167+ function ngAfterViewInit ( ) {
168+
169+ // At this point, after the view has been initialized, both of the
170+ // query list values are available - both itemBList, which was
171+ // injected via the constructor, and itemAList, which was just
172+ // injected as a property.
173+ console . warn ( "ngAfterViewInit()" ) ;
174+ console . log ( "itemAList:" , vm . itemAList . length ) ;
175+ console . log ( "itemBList:" , itemBList . length ) ;
176+
177+ // Now that we finally have a reference to the itemAList, let's
178+ // subscribe to the changes of the list (which updates the current
179+ // instance but also provides a reference to the query list).
180+ vm . itemAList . changes . subscribe (
181+ function handleValue ( queryList ) {
182+
183+ console . warn ( "itemAList Change Detection (ngAfterViewInit)" ) ;
184+ console . log ( "itemAList:" , vm . itemAList . length ) ;
185+
186+ }
187+ ) ;
188+
189+ // We've already subscribed to the changes on this list; but,
190+ // let's do it again so we can see if it would pick up the initial
191+ // length of the list.
192+ itemBList . changes . subscribe (
193+ function handleValue ( queryList ) {
194+
195+ console . warn ( "itemBList Change Detection (ngAfterViewInit)" ) ;
196+ console . log ( "itemBList:" , itemBList . length ) ;
197+
198+ }
199+ ) ;
200+
201+ }
202+
203+
204+ // I get called once after the component has been instantiated and
205+ // the inputs have been bound (and observed once).
206+ function ngOnInit ( ) {
207+
208+ // While the itemBList was injected in the constructor, the
209+ // itemAList, which was part of the component meta-data, has not
210+ // been injected.
211+ console . warn ( "ngOnInit()" ) ;
212+ console . log ( "itemAList:" , ( vm . itemAList && vm . itemAList . length ) ) ;
213+ console . log ( "itemBList:" , itemBList . length ) ;
214+
215+ }
216+
217+ }
218+
219+ }
220+ ) ;
221+
222+
223+ // --------------------------------------------------------------------------- //
224+ // --------------------------------------------------------------------------- //
225+
226+
227+ // I provide a super simple Component for no other purpose than to have a
228+ // component that can be rendered in the App component.
229+ define (
230+ "ItemA" ,
231+ function registerItemA ( ) {
232+
233+ // Configure the Item component definition.
234+ return ng . core
235+ . Component ( {
236+ selector : "item-a" ,
237+ template : "This is an ItemA!"
238+ } )
239+ . Class ( {
240+ constructor : function ItemControllerA ( ) { /* Nothing to do. */ }
241+ } )
242+ ;
243+
244+ }
245+ ) ;
246+
247+
248+ // --------------------------------------------------------------------------- //
249+ // --------------------------------------------------------------------------- //
250+
251+
252+ // I provide a super simple Component for no other purpose than to have a
253+ // component that can be rendered in the App component.
254+ define (
255+ "ItemB" ,
256+ function registerItemB ( ) {
257+
258+ // Configure the Item component definition.
259+ return ng . core
260+ . Component ( {
261+ selector : "item-b" ,
262+ template : "This is an ItemB!"
263+ } )
264+ . Class ( {
265+ constructor : function ItemControllerB ( ) { /* Nothing to do. */ }
266+ } )
267+ ;
268+
269+ }
270+ ) ;
271+
272+ </ script >
273+
274+ </ body >
275+ </ html >
0 commit comments