Skip to content

Commit e9c15dd

Browse files
author
Alexander Vakrilov
authored
Merge branch 'master' into hmr-bootstrap
2 parents 8f09598 + 6e45af0 commit e9c15dd

File tree

5 files changed

+280
-252
lines changed

5 files changed

+280
-252
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ We love PRs! Check out the [contributing guidelines](CONTRIBUTING.md) and [devel
3939
* Self-closing elements (`<Label text="Name" /><Button text="Save" />`) get parsed wrong (in this case Button gets parsed as a Label child.
4040

4141
## Get Help
42-
Please, use [github issues](https://github.com/NativeScript/nativescript-angular/issues) strictly for [reporting bugs](CONTRIBUTING.md#reporting-bugs) or [requesting features](CONTRIBUTING.md#requesting-new-features). For general questions and support, check out the [NativeScript community forum](https://discourse.nativescript.org/) or ask our experts in [NativeScript community Slack channel](http://developer.telerik.com/wp-login.php?action=slack-invitation).
42+
Please, use [github issues](https://github.com/NativeScript/nativescript-angular/issues) strictly for [reporting bugs](CONTRIBUTING.md#reporting-bugs) or [requesting features](CONTRIBUTING.md#requesting-new-features). For general questions and support, check out [Stack Overflow](https://stackoverflow.com/questions/tagged/nativescript) or ask our experts in [NativeScript community Slack channel](http://developer.telerik.com/wp-login.php?action=slack-invitation).
4343

4444
![](https://ga-beacon.appspot.com/UA-111455-24/nativescript/nativescript-angular?pixel)

Diff for: nativescript-angular/directives/index.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { ListViewComponent, TemplateKeyDirective } from "./list-view-comp";
1+
import { ListViewComponent } from "./list-view-comp";
2+
import { TemplateKeyDirective } from "./templated-items-comp";
23
import { TabViewDirective, TabViewItemDirective } from "./tab-view";
34
import {
45
ActionBarComponent,
@@ -8,11 +9,8 @@ import {
89
} from "./action-bar";
910
import { AndroidFilterComponent, IosFilterComponent } from "./platform-filters";
1011

11-
export {
12-
ListViewComponent,
13-
SetupItemViewArgs,
14-
TemplateKeyDirective
15-
} from "./list-view-comp";
12+
export { ListViewComponent } from "./list-view-comp";
13+
export { SetupItemViewArgs, TemplateKeyDirective } from "./templated-items-comp";
1614

1715
export { TabViewDirective, TabViewItemDirective } from "./tab-view";
1816
export {

Diff for: nativescript-angular/directives/list-view-comp.ts

+10-241
Original file line numberDiff line numberDiff line change
@@ -1,262 +1,31 @@
11
import {
2-
AfterContentInit,
32
ChangeDetectionStrategy,
43
Component,
5-
ContentChild,
6-
Directive,
7-
DoCheck,
84
ElementRef,
9-
EmbeddedViewRef,
10-
EventEmitter,
11-
Host,
12-
Input,
13-
IterableDiffer,
145
IterableDiffers,
15-
OnDestroy,
16-
Output,
17-
TemplateRef,
18-
ViewChild,
19-
ViewContainerRef,
20-
ɵisListLikeIterable as isListLikeIterable
6+
forwardRef
217
} from "@angular/core";
22-
import { ListView, ItemEventData } from "tns-core-modules/ui/list-view";
23-
import { View, KeyedTemplate } from "tns-core-modules/ui/core/view";
24-
import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base";
25-
import { ObservableArray } from "tns-core-modules/data/observable-array";
26-
import { profile } from "tns-core-modules/profiling";
27-
28-
import { getSingleViewRecursive } from "../element-registry";
29-
import { listViewLog, listViewError, isLogEnabled } from "../trace";
30-
31-
const NG_VIEW = "_ngViewRef";
32-
33-
export class ListItemContext {
34-
constructor(
35-
public $implicit?: any,
36-
public item?: any,
37-
public index?: number,
38-
public even?: boolean,
39-
public odd?: boolean
40-
) {
41-
}
42-
}
43-
44-
export interface SetupItemViewArgs {
45-
view: EmbeddedViewRef<any>;
46-
data: any;
47-
index: number;
48-
context: ListItemContext;
49-
}
8+
import { ListView } from "tns-core-modules/ui/list-view";
9+
import { TEMPLATED_ITEMS_COMPONENT, TemplatedItemsComponent } from "./templated-items-comp";
5010

5111
@Component({
5212
selector: "ListView",
5313
template: `
5414
<DetachedContainer>
5515
<Placeholder #loader></Placeholder>
5616
</DetachedContainer>`,
57-
changeDetection: ChangeDetectionStrategy.OnPush
17+
changeDetection: ChangeDetectionStrategy.OnPush,
18+
providers: [{ provide: TEMPLATED_ITEMS_COMPONENT, useExisting: forwardRef(() => ListViewComponent)}]
5819
})
59-
export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit {
20+
export class ListViewComponent extends TemplatedItemsComponent {
6021
public get nativeElement(): ListView {
61-
return this.listView;
62-
}
63-
64-
private listView: ListView;
65-
private _items: any;
66-
private _differ: IterableDiffer<KeyedTemplate>;
67-
private _templateMap: Map<string, KeyedTemplate>;
68-
69-
@ViewChild("loader", { read: ViewContainerRef }) loader: ViewContainerRef;
70-
71-
@Output() public setupItemView = new EventEmitter<SetupItemViewArgs>();
72-
73-
@ContentChild(TemplateRef) itemTemplateQuery: TemplateRef<ListItemContext>;
74-
75-
itemTemplate: TemplateRef<ListItemContext>;
76-
77-
@Input()
78-
get items() {
79-
return this._items;
22+
return this.templatedItemsView;
8023
}
8124

82-
set items(value: any) {
83-
this._items = value;
84-
let needDiffer = true;
85-
if (value instanceof ObservableArray) {
86-
needDiffer = false;
87-
}
88-
if (needDiffer && !this._differ && isListLikeIterable(value)) {
89-
this._differ = this._iterableDiffers.find(this._items)
90-
.create((_index, item) => { return item; });
91-
}
92-
93-
this.listView.items = this._items;
94-
}
25+
protected templatedItemsView: ListView;
9526

9627
constructor(_elementRef: ElementRef,
97-
private _iterableDiffers: IterableDiffers) {
98-
this.listView = _elementRef.nativeElement;
99-
100-
this.listView.on("itemLoading", this.onItemLoading, this);
101-
}
102-
103-
ngAfterContentInit() {
104-
if (isLogEnabled()) {
105-
listViewLog("ListView.ngAfterContentInit()");
106-
}
107-
this.setItemTemplates();
108-
}
109-
110-
ngOnDestroy() {
111-
this.listView.off("itemLoading", this.onItemLoading, this);
112-
}
113-
114-
private setItemTemplates() {
115-
// The itemTemplateQuery may be changed after list items are added that contain <template> inside,
116-
// so cache and use only the original template to avoid errors.
117-
this.itemTemplate = this.itemTemplateQuery;
118-
119-
if (this._templateMap) {
120-
if (isLogEnabled()) {
121-
listViewLog("Setting templates");
122-
}
123-
124-
const templates: KeyedTemplate[] = [];
125-
this._templateMap.forEach(value => {
126-
templates.push(value);
127-
});
128-
this.listView.itemTemplates = templates;
129-
}
130-
}
131-
132-
public registerTemplate(key: string, template: TemplateRef<ListItemContext>) {
133-
if (isLogEnabled()) {
134-
listViewLog(`registerTemplate for key: ${key}`);
135-
}
136-
if (!this._templateMap) {
137-
this._templateMap = new Map<string, KeyedTemplate>();
138-
}
139-
140-
const keyedTemplate = {
141-
key,
142-
createView: () => {
143-
if (isLogEnabled()) {
144-
listViewLog(`registerTemplate for key: ${key}`);
145-
}
146-
147-
const viewRef = this.loader.createEmbeddedView(template, new ListItemContext(), 0);
148-
const resultView = getItemViewRoot(viewRef);
149-
resultView[NG_VIEW] = viewRef;
150-
151-
return resultView;
152-
}
153-
};
154-
155-
this._templateMap.set(key, keyedTemplate);
156-
}
157-
158-
@profile
159-
public onItemLoading(args: ItemEventData) {
160-
if (!args.view && !this.itemTemplate) {
161-
return;
162-
}
163-
164-
const index = args.index;
165-
const items = (<any>args.object).items;
166-
const currentItem = typeof items.getItem === "function" ? items.getItem(index) : items[index];
167-
let viewRef: EmbeddedViewRef<ListItemContext>;
168-
169-
if (args.view) {
170-
if (isLogEnabled()) {
171-
listViewLog(`onItemLoading: ${index} - Reusing existing view`);
172-
}
173-
viewRef = args.view[NG_VIEW];
174-
// Getting angular view from original element (in cases when ProxyViewContainer
175-
// is used NativeScript internally wraps it in a StackLayout)
176-
if (!viewRef && args.view instanceof LayoutBase && args.view.getChildrenCount() > 0) {
177-
viewRef = args.view.getChildAt(0)[NG_VIEW];
178-
}
179-
180-
if (!viewRef) {
181-
if (isLogEnabled()) {
182-
listViewError(`ViewReference not found for item ${index}. View recycling is not working`);
183-
}
184-
}
185-
}
186-
187-
if (!viewRef) {
188-
if (isLogEnabled()) {
189-
listViewLog(`onItemLoading: ${index} - Creating view from template`);
190-
}
191-
viewRef = this.loader.createEmbeddedView(this.itemTemplate, new ListItemContext(), 0);
192-
args.view = getItemViewRoot(viewRef);
193-
args.view[NG_VIEW] = viewRef;
194-
}
195-
196-
this.setupViewRef(viewRef, currentItem, index);
197-
198-
this.detectChangesOnChild(viewRef, index);
199-
}
200-
201-
public setupViewRef(viewRef: EmbeddedViewRef<ListItemContext>, data: any, index: number): void {
202-
const context = viewRef.context;
203-
context.$implicit = data;
204-
context.item = data;
205-
context.index = index;
206-
context.even = (index % 2 === 0);
207-
context.odd = !context.even;
208-
209-
this.setupItemView.next({ view: viewRef, data: data, index: index, context: context });
210-
}
211-
212-
@profile
213-
private detectChangesOnChild(viewRef: EmbeddedViewRef<ListItemContext>, index: number) {
214-
if (isLogEnabled()) {
215-
listViewLog(`Manually detect changes in child: ${index}`);
216-
}
217-
viewRef.markForCheck();
218-
viewRef.detectChanges();
219-
}
220-
221-
ngDoCheck() {
222-
if (this._differ) {
223-
if (isLogEnabled()) {
224-
listViewLog("ngDoCheck() - execute differ");
225-
}
226-
const changes = this._differ.diff(this._items);
227-
if (changes) {
228-
if (isLogEnabled()) {
229-
listViewLog("ngDoCheck() - refresh");
230-
}
231-
this.listView.refresh();
232-
}
233-
}
234-
}
235-
}
236-
237-
export interface ComponentView {
238-
rootNodes: Array<any>;
239-
destroy(): void;
240-
}
241-
242-
export type RootLocator = (nodes: Array<any>, nestLevel: number) => View;
243-
244-
export function getItemViewRoot(viewRef: ComponentView, rootLocator: RootLocator = getSingleViewRecursive): View {
245-
const rootView = rootLocator(viewRef.rootNodes, 0);
246-
return rootView;
247-
}
248-
249-
@Directive({ selector: "[nsTemplateKey]" })
250-
export class TemplateKeyDirective {
251-
constructor(
252-
private templateRef: TemplateRef<any>,
253-
@Host() private list: ListViewComponent) {
254-
}
255-
256-
@Input()
257-
set nsTemplateKey(value: any) {
258-
if (this.list && this.templateRef) {
259-
this.list.registerTemplate(value, this.templateRef);
260-
}
28+
_iterableDiffers: IterableDiffers) {
29+
super(_elementRef, _iterableDiffers);
26130
}
26231
}

0 commit comments

Comments
 (0)