@stackline/angular-multiselect-dropdown 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2016 Cuppa Labs
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,264 @@
1
+ # @stackline/angular-multiselect-dropdown
2
+
3
+ Angular 2 multiselect dropdown component for web applications. Easy to integrate and use.
4
+
5
+ ## Compatibility
6
+
7
+ This package version is compatible with Angular 2.x and was tested in a real Angular 2.4.10 application.
8
+
9
+ - Package: `@stackline/angular-multiselect-dropdown@2.0.3`
10
+ - Angular peer range: `>=2.0.0 <3.0.0`
11
+ - Tested Angular runtime: `2.4.10`
12
+
13
+ ## Table of Contents
14
+ ##### 1. Getting Started
15
+ ##### 2. Installation
16
+ ##### 3. Usage
17
+ ##### 4. Templates
18
+ ##### 5. Template Driven Forms support
19
+ ##### 5. Reactive Forms support
20
+ ##### 6. Settings configuration
21
+ ##### 7. Callbacks and events
22
+ ##### 8. Lazy lodaing - handle large data lists
23
+ ##### 9. Group By feature
24
+ ##### 10. Search filter for both plain list and grouped list
25
+
26
+
27
+
28
+
29
+
30
+ ## Getting Started
31
+ ### Installation
32
+ - The Mutiselect Dropdown package is published as `@stackline/angular-multiselect-dropdown`.
33
+ - Install the tested Angular 2 package:
34
+ `npm install @stackline/angular-multiselect-dropdown@2.0.3`
35
+
36
+ - Once installed import `AngularMultiSelectModule` from the installed package into your module as follows:
37
+
38
+ ### Theme option
39
+
40
+ The package ships two built-in skins:
41
+
42
+ - `classic` keeps the original compact layout and is the default.
43
+ - `material` enables the rounded chip and list-item spacing skin.
44
+
45
+ ```js
46
+ this.dropdownSettings = {
47
+ text: 'Select Countries',
48
+ enableSearchFilter: true,
49
+ theme: 'material'
50
+ };
51
+ ```
52
+
53
+ ### Usage
54
+ Import `AngularMultiSelectModule` into `NgModule` in `app.module.ts`
55
+ ```js
56
+ import { AngularMultiSelectModule } from '@stackline/angular-multiselect-dropdown/angular2-multiselect-dropdown';
57
+
58
+ @NgModule({
59
+ // ...
60
+ imports: [
61
+ AngularMultiSelectModule,
62
+ ]
63
+ // ...
64
+ })
65
+
66
+ ```
67
+
68
+ Declare the component data variables and options in your component where you want to consume the dropdown component.
69
+
70
+ ```js
71
+
72
+ import { Component, OnInit } from '@angular/core';
73
+
74
+ export class AppComponent implements OnInit {
75
+ dropdownList = [];
76
+ selectedItems = [];
77
+ dropdownSettings = {};
78
+ ngOnInit(){
79
+ this.dropdownList = [
80
+ {"id":1,"itemName":"India"},
81
+ {"id":2,"itemName":"Singapore"},
82
+ {"id":3,"itemName":"Australia"},
83
+ {"id":4,"itemName":"Canada"},
84
+ {"id":5,"itemName":"South Korea"},
85
+ {"id":6,"itemName":"Germany"},
86
+ {"id":7,"itemName":"France"},
87
+ {"id":8,"itemName":"Russia"},
88
+ {"id":9,"itemName":"Italy"},
89
+ {"id":10,"itemName":"Sweden"}
90
+ ];
91
+ this.selectedItems = [
92
+ {"id":2,"itemName":"Singapore"},
93
+ {"id":3,"itemName":"Australia"},
94
+ {"id":4,"itemName":"Canada"},
95
+ {"id":5,"itemName":"South Korea"}
96
+ ];
97
+ this.dropdownSettings = {
98
+ singleSelection: false,
99
+ text:"Select Countries",
100
+ selectAllText:'Select All',
101
+ unSelectAllText:'UnSelect All',
102
+ enableSearchFilter: true,
103
+ classes:"myclass custom-class"
104
+ };
105
+ }
106
+ onItemSelect(item:any){
107
+ console.log(item);
108
+ console.log(this.selectedItems);
109
+ }
110
+ OnItemDeSelect(item:any){
111
+ console.log(item);
112
+ console.log(this.selectedItems);
113
+ }
114
+ onSelectAll(items: any){
115
+ console.log(items);
116
+ }
117
+ onDeSelectAll(items: any){
118
+ console.log(items);
119
+ }
120
+ }
121
+ ```
122
+
123
+ Add the following component tag in you template
124
+ ```html
125
+ <angular2-multiselect [data]="dropdownList" [(ngModel)]="selectedItems"
126
+ [settings]="dropdownSettings"
127
+ (onSelect)="onItemSelect($event)"
128
+ (onDeSelect)="OnItemDeSelect($event)"
129
+ (onSelectAll)="onSelectAll($event)"
130
+ (onDeSelectAll)="onDeSelectAll($event)"></angular2-multiselect>
131
+
132
+ ```
133
+ ### Template - For custom html of menu item
134
+
135
+ ```html
136
+ <angular2-multiselect [data]="dropdownList" [(ngModel)]="selectedItems" [settings]="dropdownSettings">
137
+ <c-item>
138
+ <ng-template let-item="item">
139
+ <label style="color: #333;min-width: 150px;">{{item.itemName}}</label>
140
+ <img [src]="item.image" style="width: 30px; border: 1px solid #efefef;margin-right: 20px;" />
141
+ <label>Capital - {{item.capital}}</label>
142
+ </ng-template>
143
+ </c-item>
144
+ </angular2-multiselect>
145
+
146
+ ```
147
+
148
+ ### Template - For custom html of Selected item - badge
149
+
150
+ ```html
151
+ <angular2-multiselect [data]="dropdownList" [(ngModel)]="selectedItems" [settings]="dropdownSettings">
152
+ <c-badge>
153
+ <ng-template let-item="item">
154
+ <label style="margin: 0px;">{{item.itemName}}</label>
155
+ <img [src]="item.image" style="width: 16px; margin-right: 5px;" />
156
+ </ng-template>
157
+ </c-badge>
158
+ </angular2-multiselect>
159
+
160
+ ```
161
+
162
+ ### Template Driven Forms support
163
+
164
+ ```html
165
+
166
+ <form (ngSubmit)="onSubmit()" #loginForm="ngForm" style="border: 1px solid #ccc; padding: 10px;">
167
+ <div class="form-group">
168
+ <label for="name">Skills</label>
169
+ <angular2-multiselect [data]="itemList" [(ngModel)]="formModel.skills"
170
+ [settings]="settings"
171
+ (onSelect)="onItemSelect($event)"
172
+ (onDeSelect)="OnItemDeSelect($event)"
173
+ (onSelectAll)="onSelectAll($event)"
174
+ (onDeSelectAll)="onDeSelectAll($event)" name="skills">
175
+ </angular2-multiselect>
176
+ </div>
177
+ </form>
178
+
179
+ ```
180
+
181
+ ```js
182
+
183
+ formModel = {
184
+ name: '',
185
+ email: 'ascasc@aa.com',
186
+ skills: [{ "id": 1, "itemName": "Angular" }]
187
+ };
188
+
189
+ ```
190
+
191
+ ### Reactive Forms support
192
+
193
+ ```html
194
+
195
+ <form [formGroup]="userForm" novalidate style="border: 1px solid #ccc; padding: 10px;">
196
+ <div class="form-group">
197
+ <label for="name">Skills</label>
198
+ <angular2-multiselect [data]="itemList" [(ngModel)]="selectedItems"
199
+ [settings]="settings"
200
+ (onSelect)="onItemSelect($event)"
201
+ (onDeSelect)="OnItemDeSelect($event)"
202
+ (onSelectAll)="onSelectAll($event)"
203
+ (onDeSelectAll)="onDeSelectAll($event)" formControlName="skills">
204
+ </angular2-multiselect>
205
+ </div>
206
+ </form>
207
+
208
+ ```
209
+
210
+ ```js
211
+ userForm: FormGroup;
212
+ this.userForm = this.fb.group({
213
+ name: '',
214
+ email: ['', Validators.required],
215
+ skills: [[], Validators.required]
216
+ });
217
+
218
+ ```
219
+
220
+ ### Settings
221
+ The following list of settings are supported by the component. Configure the settings to meet your requirement.
222
+
223
+ | Setting |Type | Description | Default Value |
224
+ |:--- |:--- |:--- |:--- |
225
+ | singleSelection | Boolean | To set the dropdown for single item selection only. | false |
226
+ | text | String | Text to be show in the dropdown, when no items are selected. | 'Select' |
227
+ | enableCheckAll | Boolean | Enable the option to select all items in list | false |
228
+ | selectAllText | String | Text to display as the label of select all option | Select All |
229
+ | unSelectAllText | String | Text to display as the label of unSelect option | UnSelect All |
230
+ | enableSearchFilter | Boolean | Enable filter option for the list. | false |
231
+ | maxHeight | Number | Set maximum height of the dropdown list in px. | 300 |
232
+ | badgeShowLimit | Number | Limit the number of badges/items to show in the input field. If not set will show all selected. | All |
233
+ | classes | String | Custom classes to the dropdown component. Classes are added to the dropdown selector tag. To add multiple classes, the value should be space separated class names.| '' |
234
+ | limitSelection | Number | Limit the selection of number of items from the dropdown list. Once the limit is reached, all unselected items gets disabled. | none |
235
+ | disabled | Boolean | Disable the dropdown | false |
236
+ | searchPlaceholderText | String | Custom text for the search placeholder text. Default value would be 'Search' | 'Search' |
237
+ | groupBy | String | Name of the field by which the list should be grouped. | none |
238
+ | searchAutofocus | Boolean | Autofocus search input field| true |
239
+ | labelKey | String | The property name which should be rendered as label in the dropdown| itemName |
240
+
241
+
242
+ ### Callback Methods
243
+ - `onSelect` - Return the selected item on selection.
244
+ Example : (onSelect)="onItemSelect($event)"
245
+ - `onDeSelect` - Return the un-selected item on un-selecting.
246
+ Example : (onDeSelect)="OnItemDeSelect($event)"
247
+ - `onSelectAll` - Return the list of all selected items.
248
+ Example : (onSelectAll)="onSelectAll($event)"
249
+ - `onDeSelectAll` - Returns an empty array.
250
+ Example : (onDeSelectAll)="onDeSelectAll($event)"
251
+ - `onOpen` - Callback method fired after the dropdown opens
252
+ Example : (onOpen)="onOpen($event)"
253
+ - `onClose` - Callback method, fired when the dropdown is closed
254
+ Example : (onClose)="onClose($event)"
255
+
256
+ ## Run locally
257
+ - Clone the repository or downlod the .zip,.tar files.
258
+ - Run `npm install`
259
+ - Run `ng serve` for a dev server
260
+ - Navigate to `http://localhost:4200/`
261
+ The app will automatically reload if you change any of the source files.
262
+
263
+ ## License
264
+ MIT License.
@@ -0,0 +1 @@
1
+ export * from './src/app/angular2-multiselect-dropdown/multiselect.component';
package/gulpfile.js ADDED
@@ -0,0 +1,68 @@
1
+ const gulp = require('gulp');
2
+ const sass = require('node-sass');
3
+ const inlineTemplates = require('gulp-inline-ng2-template');
4
+ const exec = require('child_process').exec;
5
+
6
+ /**
7
+ * Inline templates configuration.
8
+ * @see https://github.com/ludohenin/gulp-inline-ng2-template
9
+ */
10
+ const INLINE_TEMPLATES = {
11
+ SRC: './src/app/angular2-multiselect-dropdown/**/*.ts',
12
+ DIST: './tmp/src-inlined',
13
+ CONFIG: {
14
+ base: '/src/app/angular2-multiselect-dropdown',
15
+ target: 'es6',
16
+ useRelativePaths: true,
17
+ styleProcessor: compileSass
18
+ }
19
+ };
20
+
21
+ /**
22
+ * Inline external HTML and SCSS templates into Angular component files.
23
+ * @see: https://github.com/ludohenin/gulp-inline-ng2-template
24
+ */
25
+ gulp.task('inline-templates', () => {
26
+ return gulp.src(INLINE_TEMPLATES.SRC)
27
+ .pipe(inlineTemplates(INLINE_TEMPLATES.CONFIG))
28
+ .pipe(gulp.dest(INLINE_TEMPLATES.DIST));
29
+ });
30
+
31
+ /**
32
+ * Build ESM by running npm task.
33
+ * This is a temporary solution until ngc is supported --watch mode.
34
+ * @see: https://github.com/angular/angular/issues/12867
35
+ */
36
+ gulp.task('build:esm', ['inline-templates'], (callback) => {
37
+ exec('npm run ngcompile', function (error, stdout, stderr) {
38
+ console.log(stdout, stderr);
39
+ callback(error)
40
+ });
41
+ });
42
+
43
+ /**
44
+ * Implements ESM build watch mode.
45
+ * This is a temporary solution until ngc is supported --watch mode.
46
+ * @see: https://github.com/angular/angular/issues/12867
47
+ */
48
+ gulp.task('build:esm:watch', ['build:esm'], () => {
49
+ gulp.watch('src/**/*', ['build:esm']);
50
+ });
51
+
52
+ gulp.task('copy', () => {
53
+ return gulp.src(['package.json','LICENSE','README.md'])
54
+ .pipe(gulp.dest('dist/'));
55
+ });
56
+
57
+ /**
58
+ * Compile SASS to CSS.
59
+ * @see https://github.com/ludohenin/gulp-inline-ng2-template
60
+ * @see https://github.com/sass/node-sass
61
+ */
62
+ function compileSass(path, ext, file, callback) {
63
+ let compiledCss = sass.renderSync({
64
+ data: file,
65
+ outputStyle: 'compressed',
66
+ });
67
+ callback(null, compiledCss.css);
68
+ }
@@ -0,0 +1,119 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const glob = require('glob');
6
+
7
+
8
+ /**
9
+ * Simple Promiseify function that takes a Node API and return a version that supports promises.
10
+ * We use promises instead of synchronized functions to make the process less I/O bound and
11
+ * faster. It also simplifies the code.
12
+ */
13
+ function promiseify(fn) {
14
+ return function () {
15
+ const args = [].slice.call(arguments, 0);
16
+ return new Promise((resolve, reject) => {
17
+ fn.apply(this, args.concat([function (err, value) {
18
+ if (err) {
19
+ reject(err);
20
+ } else {
21
+ resolve(value);
22
+ }
23
+ }]));
24
+ });
25
+ };
26
+ }
27
+
28
+ const readFile = promiseify(fs.readFile);
29
+ const writeFile = promiseify(fs.writeFile);
30
+
31
+ /**
32
+ * Inline resources in a tsc/ngc compilation.
33
+ * @param projectPath {string} Path to the project.
34
+ */
35
+ function inlineResources(projectPath) {
36
+
37
+ // Match only TypeScript files in projectPath.
38
+ const files = glob.sync('**/*.ts', {cwd: projectPath});
39
+
40
+ // For each file, inline the templates and styles under it and write the new file.
41
+ return Promise.all(files.map(filePath => {
42
+ const fullFilePath = path.join(projectPath, filePath);
43
+ return readFile(fullFilePath, 'utf-8')
44
+ .then(content => inlineResourcesFromString(content, url => {
45
+ // Resolve the template url.
46
+ return path.join(path.dirname(fullFilePath), url);
47
+ }))
48
+ .then(content => writeFile(fullFilePath, content))
49
+ .catch(err => {
50
+ console.error('An error occured: ', err);
51
+ });
52
+ }));
53
+ }
54
+
55
+ /**
56
+ * Inline resources from a string content.
57
+ * @param content {string} The source file's content.
58
+ * @param urlResolver {Function} A resolver that takes a URL and return a path.
59
+ * @returns {string} The content with resources inlined.
60
+ */
61
+ function inlineResourcesFromString(content, urlResolver) {
62
+ // Curry through the inlining functions.
63
+ return [
64
+ inlineTemplate,
65
+ inlineStyle
66
+ ].reduce((content, fn) => fn(content, urlResolver), content);
67
+ }
68
+
69
+ /**
70
+ * Inline the templates for a source file. Simply search for instances of `templateUrl: ...` and
71
+ * replace with `template: ...` (with the content of the file included).
72
+ * @param content {string} The source file's content.
73
+ * @param urlResolver {Function} A resolver that takes a URL and return a path.
74
+ * @return {string} The content with all templates inlined.
75
+ */
76
+ function inlineTemplate(content, urlResolver) {
77
+ return content.replace(/templateUrl:\s*'([^']+?\.html)'/g, function (m, templateUrl) {
78
+ const templateFile = urlResolver(templateUrl);
79
+ const templateContent = fs.readFileSync(templateFile, 'utf-8');
80
+ const shortenedTemplate = templateContent
81
+ .replace(/([\n\r]\s*)+/gm, ' ')
82
+ .replace(/"/g, '\\"');
83
+ return `template: "${shortenedTemplate}"`;
84
+ });
85
+ }
86
+
87
+
88
+ /**
89
+ * Inline the styles for a source file. Simply search for instances of `styleUrls: [...]` and
90
+ * replace with `styles: [...]` (with the content of the file included).
91
+ * @param urlResolver {Function} A resolver that takes a URL and return a path.
92
+ * @param content {string} The source file's content.
93
+ * @return {string} The content with all styles inlined.
94
+ */
95
+ function inlineStyle(content, urlResolver) {
96
+ return content.replace(/styleUrls:\s*(\[[\s\S]*?\])/gm, function (m, styleUrls) {
97
+ const urls = eval(styleUrls);
98
+ return 'styles: ['
99
+ + urls.map(styleUrl => {
100
+ const styleFile = urlResolver(styleUrl);
101
+ const styleContent = fs.readFileSync(styleFile, 'utf-8');
102
+ const shortenedStyle = styleContent
103
+ .replace(/([\n\r]\s*)+/gm, ' ')
104
+ .replace(/"/g, '\\"');
105
+ return `"${shortenedStyle}"`;
106
+ })
107
+ .join(',\n')
108
+ + ']';
109
+ });
110
+ }
111
+
112
+ module.exports = inlineResources;
113
+ module.exports.inlineResourcesFromString = inlineResourcesFromString;
114
+
115
+ // Run inlineResources if module is being called directly from the CLI with arguments.
116
+ if (require.main === module && process.argv.length > 2) {
117
+ console.log('Inlining resources from project:', process.argv[2]);
118
+ return inlineResources(process.argv[2]);
119
+ }