├── LICENSE
├── README.md
├── bower.json
├── dist
├── mdr-select2.js
└── mdr-select2.min.js
├── gulpfile.js
├── package.json
└── src
└── mdr-select2.js
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 modulr
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Angular Select2
2 | Angular Select2 is an Angularjs component that can replacement for select boxes.
3 |
4 |
5 | 
6 |
7 | ## Features
8 |
9 | - Uses the native Angularjs scope for data binding
10 | - Fast and lightweight
11 | - Remote and local data support
12 | - Big data support
13 |
14 |
15 | ## Requirements
16 |
17 | - [Angularjs](https://angularjs.org/)
18 | - [Bootstrap 3.](http://getbootstrap.com/)
19 | - [Selec2.](https://select2.github.io/)
20 |
21 | ## Quick start
22 |
23 | Several quick start options are available:
24 |
25 | - [Download the latest release](https://github.com/Modulr/mdr-angular-select2/archive/master.zip)
26 | - Clone the repo: `git clone https://github.com/Modulr/mdr-angular-select2.git`.
27 | - Install with [Bower](http://bower.io/): `bower install mdr-angular-select2`.
28 | - Install with [npm](https://www.npmjs.com): `npm install mdr-angular-select2`.
29 |
30 | ## What's included
31 |
32 | ```
33 | mdr-angular-select2/
34 | dist/
35 | ├── mdr-select2.js
36 | └── mdr-select2.min.js
37 | ```
38 |
39 | ## Documentation
40 |
41 | ### Usage
42 |
43 | ##### Load JS
44 |
45 | ```html
46 |
47 | ```
48 |
49 | ##### Code
50 |
51 | ```js
52 | angular.module('MyApp', ['mdr.select2'])
53 | ```
54 |
55 | ##### HTML View or Templates
56 |
57 | > Basic Directive
58 |
59 | ```html
60 |
61 | ```
62 |
63 | > Complete Directive (All attributes)
64 |
65 | ```html
66 |
67 | ```
68 |
69 | ### API
70 |
71 | ##### Attributes
72 |
73 | Attribute | Type | Description
74 | --- | --- | ---
75 | url | `string` | *Is the path where you get list of items.*
76 | src | `array` | *Collection of objects.*
77 | options | `string` | *Dynamically generate a list of elements.*
78 | model | `object` | *Get model selected (Output).*
79 | selected | `object` | *Set select value by track (Input).*
80 | allow-clear | `boolean` | *If required clear selection the component is marked as true.*
81 | placeholder | `string` | *Text into placeholder.*
82 | disabled | `boolean` | *If required disable the component is marked as true.*
83 | required | `boolean` | *If is required the component is marked as true.*
84 |
85 | ## How to contribute
86 |
87 | All contributions are very welcome, We love it. There are several ways to help out:
88 |
89 | - Create an [issue](https://github.com/Modulr/mdr-angular-select2/issues) on GitHub, if you have found a bug
90 | - Write test cases for open bug issues
91 | - Write patches for open bug/feature issues, preferably with test cases included
92 | - Contribute to the documentation
93 |
94 | There are a few guidelines that we need contributors to follow so that we have a chance of keeping on top of things.
95 |
96 | If you want to making changes Better avoid working directly on the `master` branch, to avoid conflicts if you pull in updates from origin, so, if make your contribution under the branch [`dev`](https://github.com/Modulr/mdr-angular-select2/tree/dev), into folder `src/`.
97 |
98 | ## Community
99 |
100 | - Implementation help may be found at Stack Overflow (tagged [`mdr-select2`](http://stackoverflow.com/questions/tagged/mdr-select2)).
101 |
102 | ## Creators
103 |
104 | [@AlfredoBarronC](https://twitter.com/AlfredoBarronC)
105 |
106 | ## Copyright and license
107 |
108 | Code and documentation (c) Copyright 2015 Modulr. Code published under [license MIT](https://github.com/Modulr/mdr-angular-select2/blob/master/LICENSE)
109 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mdr-angular-select2",
3 | "version": "1.0.6",
4 | "description": "Select2 for angular",
5 | "main": "dist/mdr-select2.js",
6 | "authors": [
7 | "Alfredo Barron"
8 | ],
9 | "license": "MIT",
10 | "keywords": [
11 | "modulr",
12 | "select",
13 | "select2",
14 | "angular",
15 | "bootstrap",
16 | "components",
17 | "directive"
18 | ],
19 | "moduleType": [],
20 | "homepage": "",
21 | "ignore": [
22 | "**/.*"
23 | ],
24 | "dependencies": {
25 | "angular": "angularjs#~1.4.8",
26 | "bootstrap": "~3.3.6",
27 | "select2": "~4.0.1"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/dist/mdr-select2.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular
5 | .module('mdr.select2', [])
6 | .directive('mdrSelect2', [function(){
7 | /**
8 | * @param url {string}
9 | * @param src {array}
10 | * @param options {string}
11 | * @param model {object}
12 | * @param selected {object}
13 | * @param allow-clear {boolean}
14 | * @param placeholder {string}
15 | * @param disabled {boolean}
16 | * @param required {boolean}
17 | */
18 | return {
19 | restrict: 'E',
20 | controller: 'mdrSelect2Ctrl',
21 | scope: {
22 | url: '@',
23 | src: '=',
24 | options: '@',
25 | model: '=',
26 | selected: '=',
27 | allowClear: '@',
28 | placeholder: '@',
29 | disabled: '=',
30 | required: '='
31 | },
32 | template: ' '
33 | };
34 | }])
35 | .controller('mdrSelect2Ctrl', ['$scope', '$element', '$attrs', 'mdrSelect2Service', function($scope, $element, $attrs, mdrSelect2Service){
36 |
37 | $scope.placeholder = 'Select';
38 | $scope.allowClear = false;
39 |
40 | initialize();
41 |
42 | // Cuando cambia el scope url se cargan los datos
43 | // When scope url change data is loaded
44 | $scope.$watch('url', function(newValue, oldValue)
45 | {
46 | if(newValue !== undefined){
47 |
48 | var lastChar = newValue.substr(-1);
49 | // Si el ultimo caracter no es una barra
50 | // If lastChar is not a slash
51 | if (lastChar !== '/') {
52 |
53 | var options = getOptions();
54 | $scope[options.collection] = [];
55 | setPlaceholder('Loading...');
56 |
57 | mdrSelect2Service.find(newValue)
58 | .then(function (data) {
59 | if (data.length <= 0 || data.length === undefined){
60 | setPlaceholder('No results found');
61 | } else {
62 | $scope[options.collection] = data;
63 | initialize();
64 | selected($scope.selected);
65 | }
66 | })
67 | .catch(function (error) {
68 | setPlaceholder('No results found');
69 | });
70 | }
71 | }
72 | });
73 | // Cuando cambia el scope src se cargan los datos
74 | // When scope src change data is loaded
75 | $scope.$watchCollection('src', function(newValue, oldValue)
76 | {
77 | if(newValue !== undefined){
78 | var options = getOptions();
79 | $scope[options.collection] = newValue;
80 | initialize();
81 | selected($scope.selected);
82 | }
83 | });
84 | // Cuando cambia el scope model
85 | // When scope model change
86 | $scope.$watch('model', function(newValue, oldValue)
87 | {
88 | // Si el scope modelo es undefined o null
89 | // If scope model is undefined or null
90 | if(newValue === undefined || newValue === null){
91 | // Se inicializa (limpia) el modelo y el elemento select2
92 | // Model and select2 element initialize (clear)
93 | $scope.model = {};
94 | setTimeout(function() {
95 | $("#selectId_" + $scope.$id).val('').trigger('change.select2');
96 | },0);
97 | }
98 | });
99 | // Cuando cambia selected se manda llamar la funcion selected
100 | // When scope selected change selected function is called
101 | $scope.$watch('selected', function(newValue, oldValue)
102 | {
103 | selected(newValue);
104 | });
105 | // Metodo que inicializa el elemento select2
106 | // Method initialize select2 element
107 | function initialize()
108 | {
109 | setTimeout(function() {
110 | $("#selectId_" + $scope.$id).select2({
111 | placeholder: $scope.placeholder,
112 | allowClear: $scope.allowClear
113 | });
114 | },0);
115 | }
116 | // Metodo que establece el placeholder del elemento select2
117 | // Method establish placeholder in select2 element
118 | function setPlaceholder(placeholder)
119 | {
120 | setTimeout(function() {
121 | $("#selectId_" + $scope.$id).select2({
122 | placeholder: placeholder
123 | });
124 | },0);
125 | }
126 | // Metodo que asigna el ng-model y el val en el elemento select2
127 | // Method assign ng-model value and select2 element val
128 | function selected(value)
129 | {
130 | if(value !== undefined){
131 | var options = getOptions();
132 | angular.forEach($scope[options.collection], function(val, key){
133 | if(value == val[options.track]){
134 | $scope.model = val;
135 | setTimeout(function() {
136 | $("#selectId_" + $scope.$id).val(value).trigger("change");
137 | },0);
138 | return false;
139 | }
140 | });
141 | }
142 | }
143 | // Metodo que obtiene las opciones (coleccion y track)
144 | // Method get options (collection and track)
145 | function getOptions()
146 | {
147 | var parts = $scope.options.split(' ');
148 | var posCollection = parts.indexOf('in');
149 |
150 | var posTrack = parts.indexOf('track');
151 | var track = parts[posTrack+2].split('.');
152 |
153 | var options = {
154 | collection: parts[posCollection+1],
155 | track: track[1]
156 | };
157 | return options;
158 | }
159 | }])
160 | .factory('mdrSelect2Service', ['$http', '$q', function($http, $q){
161 | return{
162 | // Se obtiene la coleccion del API
163 | // Get collection from API
164 | find:function(url){
165 | var deferred = $q.defer();
166 |
167 | $http.get(url)
168 | .success(function(data){
169 | deferred.resolve(data);
170 | })
171 | .error(function(error){
172 | deferred.reject(error);
173 | });
174 |
175 | return deferred.promise;
176 | }
177 | };
178 | }]);
179 |
180 | })();
181 |
--------------------------------------------------------------------------------
/dist/mdr-select2.min.js:
--------------------------------------------------------------------------------
1 | !function(){"use strict";angular.module("mdr.select2",[]).directive("mdrSelect2",[function(){return{restrict:"E",controller:"mdrSelect2Ctrl",scope:{url:"@",src:"=",options:"@",model:"=",selected:"=",allowClear:"@",placeholder:"@",disabled:"=",required:"="},template:' '}}]).controller("mdrSelect2Ctrl",["$scope","$element","$attrs","mdrSelect2Service",function(e,t,l,o){function c(){setTimeout(function(){$("#selectId_"+e.$id).select2({placeholder:e.placeholder,allowClear:e.allowClear})},0)}function n(t){setTimeout(function(){$("#selectId_"+e.$id).select2({placeholder:t})},0)}function i(t){if(void 0!==t){var l=r();angular.forEach(e[l.collection],function(o,c){return t==o[l.track]?(e.model=o,setTimeout(function(){$("#selectId_"+e.$id).val(t).trigger("change")},0),!1):void 0})}}function r(){var t=e.options.split(" "),l=t.indexOf("in"),o=t.indexOf("track"),c=t[o+2].split("."),n={collection:t[l+1],track:c[1]};return n}e.placeholder="Select",e.allowClear=!1,c(),e.$watch("url",function(t,l){if(void 0!==t){var d=t.substr(-1);if("/"!==d){var s=r();e[s.collection]=[],n("Loading..."),o.find(t).then(function(t){t.length<=0||void 0===t.length?n("No results found"):(e[s.collection]=t,c(),i(e.selected))})["catch"](function(e){n("No results found")})}}}),e.$watchCollection("src",function(t,l){if(void 0!==t){var o=r();e[o.collection]=t,c(),i(e.selected)}}),e.$watch("model",function(t,l){(void 0===t||null===t)&&(e.model={},setTimeout(function(){$("#selectId_"+e.$id).val("").trigger("change.select2")},0))}),e.$watch("selected",function(e,t){i(e)})}]).factory("mdrSelect2Service",["$http","$q",function(e,t){return{find:function(l){var o=t.defer();return e.get(l).success(function(e){o.resolve(e)}).error(function(e){o.reject(e)}),o.promise}}}])}();
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var rename = require('gulp-rename');
3 | var uglify = require('gulp-uglify');
4 |
5 | var DEST = 'dist/';
6 |
7 | gulp.task('minify-js', function() {
8 | return gulp.src('src/*.js')
9 | .pipe(gulp.dest(DEST))
10 | .pipe(uglify())
11 | .pipe(rename({ extname: '.min.js' }))
12 | .pipe(gulp.dest(DEST));
13 | });
14 |
15 | gulp.task('default', ['minify-js']);
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mdr-angular-select2",
3 | "version": "1.0.6",
4 | "description": "Select2 for angular",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "modulr",
11 | "select",
12 | "select2",
13 | "angular",
14 | "bootstrap",
15 | "components",
16 | "directive"
17 | ],
18 | "author": "Alfredo Barron",
19 | "license": "MIT",
20 | "devDependencies": {
21 | "gulp": "^3.9.0",
22 | "gulp-rename": "^1.2.2",
23 | "gulp-uglify": "^1.4.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/mdr-select2.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular
5 | .module('mdr.select2', [])
6 | .directive('mdrSelect2', [function(){
7 | /**
8 | * @param url {string}
9 | * @param src {array}
10 | * @param options {string}
11 | * @param model {object}
12 | * @param selected {object}
13 | * @param allow-clear {boolean}
14 | * @param placeholder {string}
15 | * @param disabled {boolean}
16 | * @param required {boolean}
17 | */
18 | return {
19 | restrict: 'E',
20 | controller: 'mdrSelect2Ctrl',
21 | scope: {
22 | url: '@',
23 | src: '=',
24 | options: '@',
25 | model: '=',
26 | selected: '=',
27 | allowClear: '@',
28 | placeholder: '@',
29 | disabled: '=',
30 | required: '='
31 | },
32 | template: ' '
33 | };
34 | }])
35 | .controller('mdrSelect2Ctrl', ['$scope', '$element', '$attrs', 'mdrSelect2Service', function($scope, $element, $attrs, mdrSelect2Service){
36 |
37 | $scope.placeholder = 'Select';
38 | $scope.allowClear = false;
39 |
40 | initialize();
41 |
42 | // Cuando cambia el scope url se cargan los datos
43 | // When scope url change data is loaded
44 | $scope.$watch('url', function(newValue, oldValue)
45 | {
46 | if(newValue !== undefined){
47 |
48 | var lastChar = newValue.substr(-1);
49 | // Si el ultimo caracter no es una barra
50 | // If lastChar is not a slash
51 | if (lastChar !== '/') {
52 |
53 | var options = getOptions();
54 | $scope[options.collection] = [];
55 | setPlaceholder('Loading...');
56 |
57 | mdrSelect2Service.find(newValue)
58 | .then(function (data) {
59 | if (data.length <= 0 || data.length === undefined){
60 | setPlaceholder('No results found');
61 | } else {
62 | $scope[options.collection] = data;
63 | initialize();
64 | selected($scope.selected);
65 | }
66 | })
67 | .catch(function (error) {
68 | setPlaceholder('No results found');
69 | });
70 | }
71 | }
72 | });
73 | // Cuando cambia el scope src se cargan los datos
74 | // When scope src change data is loaded
75 | $scope.$watchCollection('src', function(newValue, oldValue)
76 | {
77 | if(newValue !== undefined){
78 | var options = getOptions();
79 | $scope[options.collection] = newValue;
80 | initialize();
81 | selected($scope.selected);
82 | }
83 | });
84 | // Cuando cambia el scope model
85 | // When scope model change
86 | $scope.$watch('model', function(newValue, oldValue)
87 | {
88 | // Si el scope modelo es undefined o null
89 | // If scope model is undefined or null
90 | if(newValue === undefined || newValue === null){
91 | // Se inicializa (limpia) el modelo y el elemento select2
92 | // Model and select2 element initialize (clear)
93 | $scope.model = {};
94 | setTimeout(function() {
95 | $("#selectId_" + $scope.$id).val('').trigger('change.select2');
96 | },0);
97 | }
98 | });
99 | // Cuando cambia selected se manda llamar la funcion selected
100 | // When scope selected change selected function is called
101 | $scope.$watch('selected', function(newValue, oldValue)
102 | {
103 | selected(newValue);
104 | });
105 | // Metodo que inicializa el elemento select2
106 | // Method initialize select2 element
107 | function initialize()
108 | {
109 | setTimeout(function() {
110 | $("#selectId_" + $scope.$id).select2({
111 | placeholder: $scope.placeholder,
112 | allowClear: $scope.allowClear
113 | });
114 | },0);
115 | }
116 | // Metodo que establece el placeholder del elemento select2
117 | // Method establish placeholder in select2 element
118 | function setPlaceholder(placeholder)
119 | {
120 | setTimeout(function() {
121 | $("#selectId_" + $scope.$id).select2({
122 | placeholder: placeholder
123 | });
124 | },0);
125 | }
126 | // Metodo que asigna el ng-model y el val en el elemento select2
127 | // Method assign ng-model value and select2 element val
128 | function selected(value)
129 | {
130 | if(value !== undefined){
131 | var options = getOptions();
132 | angular.forEach($scope[options.collection], function(val, key){
133 | if(value == val[options.track]){
134 | $scope.model = val;
135 | setTimeout(function() {
136 | $("#selectId_" + $scope.$id).val(value).trigger("change");
137 | },0);
138 | return false;
139 | }
140 | });
141 | }
142 | }
143 | // Metodo que obtiene las opciones (coleccion y track)
144 | // Method get options (collection and track)
145 | function getOptions()
146 | {
147 | var parts = $scope.options.split(' ');
148 | var posCollection = parts.indexOf('in');
149 |
150 | var posTrack = parts.indexOf('track');
151 | var track = parts[posTrack+2].split('.');
152 |
153 | var options = {
154 | collection: parts[posCollection+1],
155 | track: track[1]
156 | };
157 | return options;
158 | }
159 | }])
160 | .factory('mdrSelect2Service', ['$http', '$q', function($http, $q){
161 | return{
162 | // Se obtiene la coleccion del API
163 | // Get collection from API
164 | find:function(url){
165 | var deferred = $q.defer();
166 |
167 | $http.get(url)
168 | .success(function(data){
169 | deferred.resolve(data);
170 | })
171 | .error(function(error){
172 | deferred.reject(error);
173 | });
174 |
175 | return deferred.promise;
176 | }
177 | };
178 | }]);
179 |
180 | })();
181 |
--------------------------------------------------------------------------------