AngularJS adaptation of ui-select for x-editable with the additional ability to add objects on the fly
Hello!
Recently I happened to adapt ui-select to x-editable in Angular and since I had to spend a certain amount of time collecting bit by bit the most acceptable option, today I decided to share my best practices with you, in the hope that it will save someone time.
In short, the resulting directive replaces the standard editable-select, plus the additional ability to add objects on the fly.
Now in more detail.
To start, I’ll start from the end and give the code for a directive that allows you to add a button to ui-select. A function is hung on this button, in my case, a function that calls a modal window (ui-bootstrap modal) with the form of adding a new object:
In principle, the code is extremely simple, so I will focus on a couple of points. Firstly, ui-select does not close after clicking a button, but closes if you click somewhere on the modal window. Therefore, I had to add a crutch with $ timeout.
Secondly (regarding the last if else): if no elements are found in the ui-select search, I pass the search value to the method in order to autofill the form with this value in the future and thus save a little time.
Now the main directive:
The directive was made in the image of the standard xeditable directives, and then slightly redone.
One of the main problems that I encountered when writing the directive was the inability to change the model, so an additional method for on-select was added.
You can use all this like this:
And finally, a bonus. If you use this thing in table-responsive (bootstrap), then the drop-down list can be overridden by the table (especially if it consists of a couple of rows). You can fix this by adding css:
Conclusion . There may be many options for implementing this directive, and there are probably better options among them. I published my work only because the official xeditable documentation does not yet mention ui-select support, and also because I found little information on the topic, and the one that I found differs.
I hope that the guru of the angular will help me improve my directive, as well as the fact that this article is useful to someone.
UPD . A small example: plnkr.co/edit/5dPKCnzbKE8D9XIR8ocX?p=preview
Recently I happened to adapt ui-select to x-editable in Angular and since I had to spend a certain amount of time collecting bit by bit the most acceptable option, today I decided to share my best practices with you, in the hope that it will save someone time.
In short, the resulting directive replaces the standard editable-select, plus the additional ability to add objects on the fly.
Now in more detail.
To start, I’ll start from the end and give the code for a directive that allows you to add a button to ui-select. A function is hung on this button, in my case, a function that calls a modal window (ui-bootstrap modal) with the form of adding a new object:
app.directive("addNewItem", function($timeout) {
return {
restrict: "A",
link: function(scope, e, attrs) {
var method = attrs.addNewItem;
var template = ""+
""+
"";
e.find('li.ui-select-choices-group').append(template);
e.find('div.add-new-item-container button').bind('click', function() {
// workaround for closing ui-select
$timeout(function() {
e.trigger("click");
});
var searchResult = e.find('li.ui-select-choices-row').length;
if ( ! searchResult ) {
var value = e.find('input.ui-select-search').val();
scope[method].apply(null, [value]);
} else {
scope[method].apply();
}
});
}
}
})
In principle, the code is extremely simple, so I will focus on a couple of points. Firstly, ui-select does not close after clicking a button, but closes if you click somewhere on the modal window. Therefore, I had to add a crutch with $ timeout.
Secondly (regarding the last if else): if no elements are found in the ui-select search, I pass the search value to the method in order to autofill the form with this value in the future and thus save a little time.
Now the main directive:
app.directive('editableUiSelect',
['editableDirectiveFactory', 'editableNgOptionsParser',
function(editableDirectiveFactory, editableNgOptionsParser) {
var dir = editableDirectiveFactory({
directiveName: 'editableUiSelect',
inputTpl: ' ',
render: function() {
this.parent.render.call(this);
var parsed = editableNgOptionsParser(this.attrs.eNgOptions);
this.inputEl.attr('ng-model', 'editable.entity');
// слева директива, описанная вначале,
// справа - метод, в моем случае вызывающий модальное окно с формой добавления
this.inputEl.attr('add-new-item', 'addNewItem');
// поскольку модель самостоятельно не меняется, пришлось добавить этот метод
this.inputEl.attr('on-select', 'setModel($item)');
this.inputEl.attr('theme', 'select2');
this.inputEl.css('width', '200px');
var html = " "+
"" +
" ";
this.inputEl.removeAttr('ng-options');
this.inputEl.append(html);
}
});
return dir;
}]);
The directive was made in the image of the standard xeditable directives, and then slightly redone.
One of the main problems that I encountered when writing the directive was the inability to change the model, so an additional method for on-select was added.
You can use all this like this:
{{ entity.property.name }}
And finally, a bonus. If you use this thing in table-responsive (bootstrap), then the drop-down list can be overridden by the table (especially if it consists of a couple of rows). You can fix this by adding css:
.table-responsive .ui-select-dropdown {
position: relative !important;
}
Conclusion . There may be many options for implementing this directive, and there are probably better options among them. I published my work only because the official xeditable documentation does not yet mention ui-select support, and also because I found little information on the topic, and the one that I found differs.
I hope that the guru of the angular will help me improve my directive, as well as the fact that this article is useful to someone.
UPD . A small example: plnkr.co/edit/5dPKCnzbKE8D9XIR8ocX?p=preview