angularjs ui-select trouble with creating custom directive - angularjs

Good day! I need to create directive with ui-select inside.
Here is directive's controller and template:
app.controller("servicesCtrl", ["$resource", '$scope', function($resource, $scope){
$scope.clinicServices = [];
console.log($scope.data);
var Services = $resource(window.baseurl + "services/getAllbyClinic", null, {
get:{responceType: "JSON", isArray: false, method: 'POST'}
});
$scope.refresh = function(service){
if(service.length < 1) return false;
Services.get({service: service},function(data){
$scope.clinicServices = data.services;
});
};
}]);
<ui-select
multiple
tagging
tagging-label="false"
ng-model="$parent.data"
theme="bootstrap"
title="Выберите услугу"
search-enabled="true"
>
<ui-select-match placeholder="Введите услугу">{{$item.name}}</ui-select-match>
<ui-select-choices repeat="clinicService in clinicServices" refresh="refresh($select.search)">
<div ng-bind-html="(clinicService.name | highlight: $select.search)"></div>
</ui-select-choices>
</ui-select>
{{data}}
And here is directive initialization.
app.directive('services', function() {
return {
restrict: 'E',
templateUrl: window.baseurl + 'views/services',
scope: {
data: "=ngModel"
},
controller: "servicesCtrl",
controllerAs: "services"
}
});
<services ng-model="meEvent.services"></services>
Can't render $scope.data into view from servicesCtrl to edit previously selected data. There are an object inside $scope.data, but empty view's field. I tried ng-model="$parent.data" and ng-model="data", but have no effect.

There where errors in my version of ui-select library

Related

Directive two way binding watch property

I'm trying to use directives in my angularjs app, it's the first i'm trying to apply, so i'm not sure if its right.
The thing is that i want to wrap the ui-select directive into another directive and then i want to watch the selec if a new value has been selected. I'm able to populate the select but i don't know why it doesn't trigger the watch... here is the controller:
.controller('IngredientesDatosGeneralesController' ,['$scope', 'PrivateAlergenosUtilsService',
'PrivateRestauranteService', 'PrivateIngredienteService',
function($scope, PrivateAlergenosUtilsService, PrivateRestauranteService,
PrivateIngredienteService){
var _this = this;
_this.PrivateIngredienteService = PrivateIngredienteService;
_this.proveedorSeleccionado = null;
_this.proveedores = [];
PrivateRestauranteService.getProveedores().then(
function(proveedores){
_this.proveedores = proveedores;
},
function(error){
_this.proveedores = [];
}
);
$scope.$watch('cntrl.proveedorSeleccionado', function(newValue,oldValue){
if (newValue && newValue!=oldValue){
_this.PrivateIngredienteService.getIngregienteDTO().id = _this.proveedorSeleccionado.id;
}
}, true);
}]);
The following is the directive:
.directive('comboDirective', [
function(){
return {
restrict : 'E',
templateUrl: 'resources/js/private/views/utils/combo/combo.html',
scope : {
seleccionado : '=',
elementos : '=',
descripcion : '#'
}
}}]);
The combo.html:
<div class="col-xs">
<label translate>{{descripcion}}</label>
</div>
<div class="col-xs">
<div class="selectStyle">
<ui-select ng-model="seleccionado" theme="bootstrap" register-custom-form-control disable-validation-message="" required>
<ui-select-match placeholder="{{'input.seleccionar' | translate}}">{{$select.selected.descripcion}}</ui-select-match>
<ui-select-choices repeat="elemento in elementos | filter: $select.search">
<div ng-bind-html="elemento.descripcion | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
<i class="fa fa-chevron-down"></i>
</div>
</div>
And finally this is how i call the directive:
<div ng-controller="IngredientesDatosGeneralesController as cntrl">
<combo-directive
seleccionado="cntrl.proveedorSeleccionado"
descripcion="formulario.proveedor"
elementos="cntrl.proveedores">
</combo-directive>
</div>
Thanks in advance
I found what was happening... i don't know why but if i put this config in the directive and using the 'cntrl.' prefix before the "seleccionado" and "elementos" values in the HTML, it works properly.
'use strict';
angular.module("private.directives")
.directive('comboDirective', [
function(){
return {
restrict : 'E',
templateUrl: 'resources/js/private/views/utils/combo/combo.html',
scope : {
seleccionado : '=',
elementos : '=',
descripcion : '#'
},
controller : ['$scope', function ($scope) {
}],
controllerAs : 'cntrl',
bindToController: true
}
}]);

Function inside factory is not accessible from custom directive

I have an angular App which has the following code in the script:
var myApp = angular.module('myApp', []);
myApp.controller('Ctrl', function($scope, FileAccessor) {
$scope.countrynames = []
});
myApp.directive('country', function() {
var directiveDefinitionObject = {
restrict: 'E',
templateUrl: 'partials/scape.html',
controllerAs: 'dm',
compile: function(scope, FileAccessor) {
FileAccessor.fetchCountryDetails('https://restcountries.eu/rest/v1/all').success(function(response) { //assigning the fetched countries to the scope object var
scope.countrynames = response;
});
}
}
return directiveDefinitionObject;
})
myApp.factory("FileAccessor", ['$http', function($http) {
return {
fetchCountryDetails: function(url) {
return $http.get(url);
}
}
}]);
Inside scape.html, the following code is placed:
<div ng-controller="Ctrl" class="container" style="height:500px" >
<select ng-model="model" ng-options="obj.name for obj in countrynames | orderBy: '-population'" placeholder="Select" autofocus>
<option value="">- Please Choose -</option>
</select>
{{model.name}}
{{model.currencies[0]}}
</div>
As we can see, I am trying to access the function which is placed inside the factory, FileAccessor from the custom directive, country.
When I run it on browser, there is this error that pops on console:
angular.min.js:86 TypeError: FileAccessor.fetchCountryDetails is not a function
Can somebody please explain what went wrong along with the fixed code?
P.S. I want the HTTP requests to be processed only through the factory(as a requirement).
Edit 1: Including the Plunkr link here: http://plnkr.co/edit/gXQKBd?p=info
Inject the service at your directive declaration, NOT in the compile function:
myApp.directive('country', function(FileAccessor) { //inject FileAccessor here
var directiveDefinitionObject = {
restrict: 'E',
templateUrl: 'partials/scape.html',
controllerAs: 'dm',
compile: function(scope) {
FileAccessor.fetchCountryDetails('https://restcountries.eu/rest/v1/all').success(function(response) { //assigning the fetched countries to the scope object var
scope.countrynames = response;
});
}
}
return directiveDefinitionObject;
})
Edit: There are quite a number of bugs inside your code, maybe you would want to read the docs?
One: Use link instead of compile, as link gives you the scope but compile doesn't:
myApp.directive('country', function(FileAccessor) {
var directiveDefinitionObject = {
restrict: 'E',
templateUrl: 'scape.html',
controllerAs: 'dm',
link: function(scope) {
scope.test="Hello";
FileAccessor.fetchCountryDetails('https://restcountries.eu/rest/v1/all').then(function(response) { //assigning the fetched countries to the scope object var
scope.countrynames = response.data;
});
}
}
return directiveDefinitionObject;
})
Two: Remove the ng-controller directive in your scape.html as this will override the of your directive:
<div class="container" style="height:500px"> //remove the ng-controller='Ctrl'
<select ng-model="model" ng-options="obj.name for obj in countrynames | orderBy: '-population'" placeholder="Select" autofocus>
<option value="">- Please Choose -</option>
</select>
{{model.name}} {{model.currencies[0]}}
</div>
Here's a working plnkr
After analysing your code and agreeing with #CozyAzure, I could see that there is this controller Ctrl which doesn't do anything in the script.
Do you really need this? Eliminate it from your script.js and index.html and do a run. This would surely fetch the data in the desired way.

How to pass data from controller to custom directive

I am creating a custom directive in AngularJS. This directive should open a popup to display data. The code for the popup is in another html page and the custom directive injects the code into my main page. I am able to open the popup however I cannot display the existing data anywhere in the pop up.
Normally, I am able to display the data in the main page however the data just do not want to go into the html injected by the custom directive.
Like this I do not get any error however it does not pass the data.
Note: I had to trim some of the code here to simplify it.
This is my custom directive:
function updateCandidatePopup() {
var directive = {};
directive.restrict = "E";
directive.scope = {};
directive.templateUrl = "UpdateCandidatePopup.html";
directive.controller = function ($scope) {
$scope.SingleCandidate;
}
return directive;
}
This is where I register it:
myApp.directive("updateCandidatePopup", UpdateCandidatePopup);
This is how I use the directive in the mainpage
<update-candidate-popup value="SingleCandidate" class="modal fade" ng-model="SingleCandidate"
id="myUpdateModal"
role="dialog"
popup-data="SingleCandidate">
zxc</update-candidate-popup>
This is the UpdateCandidatePopup.html:
<div> {{SingleCandidate.FirstName}} </div>
This is the to display the data in the pop up controller: (FYI it is still trimmed)
myApp.controller('CandidatesController', function ($scope, $http, EmployerService, CandidateService) { //we injected localservice
//Select single data for update
$scope.getSingleData = function (C_ID) {
alert(C_ID);
$http.get('http://localhost:49921/api/Candidates/?C_ID=' + C_ID).success(function (data) {
$scope.SingleCandidate = data;
$scope.FName = $scope.SingleCandidate.FirstName;
alert($scope.SingleCandidate.FirstName);
alert($scope.FName);
}).error(function () {
$scope.error = "An Error has occured while loading posts!";
});
};
});
Sorry wrong !, answered your question, here I leave I found a code that will serve for your problem. In the background to the template you want to take, you let a controller and in the statement of your policy, put you going to do with those values, I think in your case is just printing.
myApp.directive('editkeyvalue', function() {
return {
restrict: 'E',
replace: true,
scope: {
key: '=',
value: '=',
accept: "&"
},
template : '<div><label class="control-label">{{key}}</label>' +
'<label class="control-label">{{key}}</label>' +
'<input type="text" ng-model="value" />'+
'<button type="button" x-ng-click="cancel()">CANCEL</button>' +
'<button type="submit" x-ng-click="save()">SAVE</button></div>',
controller: function($scope, $element, $attrs, $location) {
$scope.save= function() {
console.log('from directive', $scope.key, $scope.value);
$scope.accept()
};
}
}
});
jsFiddle
Solved the problem like below. It was only to inject to $scope in the directive controller.
myApp.directive("updateCandidatePopup", function () {
return {
templateUrl : "UpdateCandidatePopup.html",
restrict: 'E',
controller: function ($scope) {
}
}
});

AngularJS Wrapping a ui-select in a custom directive

I'm trying to wrap a ui-select in a custom directive. (https://github.com/angular-ui/ui-select)
this.adminv2.directive('eventSelect', function() {
return {
restrict: 'E',
replace: true,
scope: {
ngModel: '=',
placeholder: '='
},
controller: function($scope, $http) {
return $scope.refreshEvents = function(searchTerm) {
return $http.get('/events/autocomplete', {
params: {
term: searchTerm
}
}).then(function(response) {
return $scope.events = response.data;
});
};
},
template: "<div>{{ngModel}}\n <ui-select ng-model=\"ngModel\"\n theme=\"bootstrap\"\n ng-disabled=\"disabled\"\n reset-search-input=\"false\">\n <ui-select-match placeholder=\"Enter an event\">{{$select.selected.name}}</ui-select-match>\n <ui-select-choices repeat=\"event in events track by $index\"\n refresh=\"refreshEvents($select.search)\"\n refresh-delay=\"0\">\n <span ng-bind-html=\"event.name | highlight: $select.search\"></span>\n <i class=\"icon-uniF111 fg type-{{raceType}} pull-right\" ng-repeat='raceType in event.racetypes'></i>\n <br>\n {{event.dates}} <i class='pull-right'>{{event.location}}</i>\n </ui-select-choices>\n </ui-select>\n</div>"
};
});
The select works properly, but the binding with ng-model doesn't work. I cannot set the model or read it.
I don't get it since it works when I use a simple template such as
<div><input ng-model="ngModel"></div>
Is there something special to do because I wrap a directive in directive ?
I managed to make the binding work by setting the ng-model in the template as
ng-model="$parent.ngModel"

AngularJS controller inside directive with binding

I have this simple code of my directive:
app.directive('ngModal', function ($parse) {
return {
restrict: 'E',
template: document.getElementById('ng-modal').innerHTML,
replace: true,
controller : "#",
name:"controllerName",
}
})
<ng-modal controller-name="ModalCtrl"></ng-modal>
And this is my controller:
app.controller('ModalCtrl', ['$scope', function ($scope) {
$scope.model = 'default text'
}])
<div ng-controller="ModalCtrl">
<input type="text" ng-model="model">
</div>
I want, that model field inside my Directive will updated automatically. But I see "default text" always inside directive and changed inside controller. How can I bind it?
You have to add a service to keep information between controllers. Controllers are always created per "view" so your ng-modal and div have different controllers in use, this is why model data is not updated between them.
Fast example:
app.service('sharedData', function() {
var sharedData = {
field: 'default text'
};
return sharedData;
});
app.directive('ngModal', function () {
return {
restrict: 'E',
template: '',
replace: true,
controller : "#",
name:"controllerName",
}
});
app.controller('ModalCtrl', ['$scope', 'sharedData', function ($scope, sharedData) {
$scope.model = sharedData;
}]);
<ng-modal controller-name="ModalCtrl">{{model.field}}</ng-modal>
<div ng-controller="ModalCtrl">
<input type="text" ng-model="model.field">
</div>

Resources