So, three parts. First the directive, and then two templates (one for the “label”, and the other for the “list”). I also added an example
// Fancy select directive
.directive('fancySelect', function($ionicModal) {
return {
/* Only use as <fancy-select> tag */
restrict : 'E',
/* Our template */
templateUrl: 'templates/directives/fancy-select.html',
/* Attributes to set */
scope: {
'items' : '=', /* Items list is mandatory */
'value' : '=' /* Selected value binding is mandatory */
},
link: function (scope, element, attrs, $filter) {
/* Default values */
scope.multiSelect = attrs.multiSelect === 'true' ? true : false;
scope.allowEmpty = attrs.allowEmpty === 'false' ? false : true;
/* Header used in ion-header-bar */
scope.headerText = attrs.headerText || '';
/* Text displayed on label */
scope.text = attrs.text || '';
scope.defaultText = attrs.text || '';
/* Notes in the right side of the label */
scope.noteText = attrs.noteText || '';
scope.noteImg = attrs.noteImg || '';
scope.noteImgClass = attrs.noteImgClass || '';
/* Instanciate ionic modal view and set params */
/* Some additionnal notes here :
*
* In previous version of the directive,
* we were using attrs.parentSelector
* to open the modal box within a selector.
*
* This is handy in particular when opening
* the "fancy select" from the right pane of
* a side view.
*
* But the problem is that I had to edit ionic.bundle.js
* and the modal component each time ionic team
* make an update of the FW.
*
* Also, seems that animations do not work
* anymore.
*
*/
$ionicModal.fromTemplateUrl(
'templates/directives/fancy-select-items.html',
{ 'scope': scope,
'animation': 'slide-left-right-ios7' }
).then(function(modal) {
scope.modal = modal;
});
/* Validate selection from header bar */
scope.validate = function (event) {
// Construct selected values and selected text
if (scope.multiSelect == true) {
// Clear values
scope.value = '';
scope.text = '';
// Loop on items
jQuery.each(scope.items, function (index, item) {
if (item.checked) {
scope.value = scope.value + item.id+';';
scope.text = scope.text + item.text+', ';
}
});
// Remove trailing comma
scope.value = scope.value.substr(0,scope.value.length - 1);
scope.text = scope.text.substr(0,scope.text.length - 2);
}
// Select first value if not nullable
if (typeof scope.value == 'undefined' || scope.value == '' || scope.value == null ) {
if (scope.allowEmpty == false) {
scope.value = scope.items[0].id;
scope.text = scope.items[0].text;
// Check for multi select
scope.items[0].checked = true;
} else {
scope.text = scope.defaultText;
}
}
// Hide modal
scope.hideItems();
}
/* Show list */
scope.showItems = function (event) {
event.preventDefault();
scope.modal.show();
}
/* Hide list */
scope.hideItems = function () {
scope.modal.hide();
}
/* Destroy modal */
scope.$on('$destroy', function() {
scope.modal.remove();
});
/* Validate single with data */
scope.validateSingle = function (item) {
// Set selected text
scope.text = item.text;
// Set selected value
scope.value = item.id;
// Hide items
scope.hideItems();
}
}
};
});
Now the code for the “label” part within the form
<ion-list>
<ion-item ng-click="showItems($event)">
{{text}}
<span class="item-note">
{{noteText}}
<img class="{{noteImgClass}}" ng-if="noteImg != ''" src="{{noteImg}}" />
</span>
</ion-item>
</ion-list>
and now for the item list :
<ion-view class="fancy-select slide-left-right-ios7 modal">
<ion-header-bar class="bar-positive">
<button ng-click="validate()" class="button button-positive button-icon ion-ios7-arrow-back"></button>
<h1 class="title">{{headerText}}</h1>
</ion-header-bar>
<ion-content>
<div class="list">
<!-- Multi select -->
<ion-toggle
ng-repeat="item in items"
ng-if="multiSelect"
ng-checked="item.checked"
ng-model="item.checked"
class="item">
<img class="fancy-select-icon" ng-if="item.icon != null" src="{{item.icon}}" alt="{{item.text}}" />
{{item.text}}
</ion-toggle>
<!-- Single select -->
<label
ng-repeat="item in items"
ng-if="!multiSelect"
class="item"
ng-click='validateSingle(item)'>
<img class="fancy-select-icon" ng-if="item.icon != null" src="{{item.icon}}" alt="{{item.text}}" />
{{item.text}}
</label>
</div>
</ion-content>
</ion-view>
An example of usage :
<fancy-select
allow-empty='false'
value="user.country.id"
text="'Country'"
header-text="'Choose country'"
items="countries">
</fancy-select>
Sorry I do not have a precise documentation but I think this can be a good start to integrate something within ionic framework. In my opinion, there are only 3 things to take care of :
-
Directive should be “generic”, but it seems that there are so many configuration possibilities (let’s say for exemple, user should be able to specify class for the header bar of the “list view”).
-
Item list should be opened in the left or right pane. I had to edit ionic modal js to make this possible. By passing the parent selector in which the list should be opened
-
Animations do not work. And it seems that the code pen here : http://codepen.io/ionic/pen/gblny is outdated (?). Code here seems different to examples in modal documentation.
A coworker also added some “Note” to the label. Made a screenshot to illustrate the concept
scope.noteText = attrs.noteText || '';
scope.noteImg = attrs.noteImg || '';
scope.noteImgClass = attrs.noteImgClass || '';