-
Notifications
You must be signed in to change notification settings - Fork 7
/
DataProvider.ts
206 lines (206 loc) · 7.89 KB
/
DataProvider.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
import Model from '../base/Model';
import Component from '../base/Component';
import Pagination from './Pagination';
import Sort from './Sort';
/**
* BaseDataProvider provides a base class for [[ActiveDataProvider]] and [[ArrayDataProvider]]
*
* For more details and usage information on BaseDataProvider, see the [guide article on data providers](guide:output-data-providers).
*
* @property-read int $count The number of data models in the current page. This property is read-only.
* @property array $keys The list of key values corresponding to [[models]]. Each data model in [[models]] is
* uniquely identified by the corresponding key value in this array.
* @property array $models The list of data models in the current page.
* @property Pagination|false $pagination The pagination object. If this is false, it means the pagination is
* disabled. Note that the type of this property differs in getter and setter. See [[getPagination()]] and
* [[setPagination()]] for details.
* @property Sort|bool $sort The sorting object. If this is false, it means the sorting is disabled. Note that
* the type of this property differs in getter and setter. See [[getSort()]] and [[setSort()]] for details.
* @property int $totalCount Total number of possible data models.
*
* @author Mahesh S Warrier <https://github.com/codespede>
*/
export default class DataProvider extends Component {
/**
* Number of data providers on the current page. Used to generate unique IDs.
*/
private static counter = 0;
/**
* An ID that uniquely identifies the data provider among all data providers.
* Generated automatically the following way in case it is not set:
*
* - First data provider ID is empty.
* - Second and all subsequent data provider IDs are: "dp-1", "dp-2", etc.
*/
public id: string;
private _sort;
private _pagination;
private _models: Model[] = [];
private _keys: string[] | void = [];
private _totalCount: number;
/**
* Model Class which can be used for resolving Attribute Labels, Hints etc.
*/
public modelClass: Model | undefined;
/**
* Promise which resolves to the number matching records for the current query.
*/
public totalCountPromise: Promise<number>;
public constructor(config) {
super(config);
Object.assign(this, config);
}
/** @inheritdoc */
public async init() {
if (this.id === null) {
if (DataProvider.counter > 0) this.id = `dp-${DataProvider.counter}`;
DataProvider.counter++;
}
await super.init.call(this);
}
/**
* Prepares the data models and keys.
*
* This method will prepare the data models and keys that can be retrieved via
* [[getModels]] and [[getKeys]].
*
* This method will be implicitly called by [[getModels]] and [[getKeys]] if it has not been called before.
*
* @param forcePrepare whether to force data preparation even if it has been done before.
*/
public async prepare(forcePrepare = false) {
if (forcePrepare || this._models.length === 0) {
this._models = await this.prepareModels();
}
if (forcePrepare || (this._keys as Array<string>).length === 0) {
this._keys = this.prepareKeys(this._models);
}
}
/**
* Prepares the keys associated with the currently available data models.
* @param models the available data models
* @return the keys
*/
public prepareKeys(models: Model[]) {}
/**
* Prepares the data models that will be made available in the current page.
* @return the available data models
*/
public async prepareModels(): Promise<Model[]> {
return new Promise<Model[]>((resolve, reject) => {});
}
/**
* Returns a value indicating the total number of data models in this data provider.
* @return total number of data models in this data provider.
*/
public async prepareTotalCount(): Promise<number> {
return 0;
}
/**
* Returns the data models in the current page.
* @return the list of data models in the current page.
*/
public async getModels(): Promise<Model[]> {
await this.prepare();
return this._models;
}
/**
* Sets the data models in the current page.
* @param models the models in the current page
*/
public setModels(models: Model[]) {
this._models = models;
}
/**
* Returns the key values associated with the data models.
* @return the list of key values corresponding to [[models]]. Each data model in [[models]]
* is uniquely identified by the corresponding key value in this array.
*/
public getKeys() {
return this._keys;
}
/**
* Returns the number of data models in the current page.
* @return the number of data models in the current page.
*/
public getCount() {
return this._models.length;
}
/**
* Returns the total number of data models.
* When [[pagination]] is false, this returns the same value as [[count]].
* Otherwise, it will call [[prepareTotalCount]] to get the count.
* @return total number of possible data models.
*/
public async getTotalCount() {
if (this._totalCount === undefined) this._totalCount = await this.prepareTotalCount();
return this._totalCount;
}
/**
* Sets the total number of data models.
* @param value the total number of data models.
*/
public setTotalCount(value: number) {
this._totalCount = value;
}
/**
* Returns the pagination object used by this data provider.
* Note that you should call [[prepare]] or [[getModels]] first to get correct values
* of [[Pagination.totalCount]] and [[Pagination::pageCount]].
* @return the pagination object. If this is false, it means the pagination is disabled.
*/
public getPagination() {
if (this._pagination === undefined) this.setPagination({});
return this._pagination;
}
/**
* Sets the pagination for this data provider.
* @param value the pagination to be used by this data provider.
* This can be one of the following:
*
* - a configuration array for creating the pagination object. The "class" element defaults
* to [[Pagination]]
* - an instance of [[Pagination]] or its subclass
* - false, if pagination needs to be disabled.
*/
public setPagination(value) {
if (value instanceof Pagination || value === false) this._pagination = value;
else this._pagination = new Pagination(value);
}
/**
* Returns the sorting object used by this data provider.
* @return the sorting object. If this is false, it means the sorting is disabled.
*/
public getSort() {
if (this._sort === undefined) this.setSort({});
return this._sort;
}
/**
* Sets the sort definition for this data provider.
* @param value the sort definition to be used by this data provider.
* This can be one of the following:
*
* - a configuration array for creating the sort definition object. The "class" element defaults
* to 'yii\data\Sort'
* - an instance of [[Sort]] or its subclass
* - false, if sorting needs to be disabled.
*/
public setSort(value) {
if (value instanceof Sort || value === false) this._sort = value;
else {
const config: any = {};
if (this.id !== undefined) config.sortParam = `${this.id}-sort`;
this._sort = new Sort({ ...value, ...config });
}
}
/**
* Refreshes the data provider.
* After calling this method, if [[getModels]], [[getKeys]] or [[getTotalCount]] is called again,
* they will re-execute the query and return the latest data available.
*/
public refresh() {
this._totalCount = null;
this._models = null;
this._keys = null;
}
}