How to implement a disable when loading directive - javascript

Hi I have a variable on my scope named loadingdata. It will have the values true or false to determine if data is loading or not. I would like to put an attribute on an element to disable it if data is loading. Here is the code I already have but it is not working:
module.directive('disableWhenLoadingData', function () {
return {
restrict: 'A',
scope: {},
link: function ($scope, element, attrs) {
$scope.$watch('loadingData', function(newValue, oldValue) {
element.attr('disabled', newValue);
});
}
};
});
any ideas

You can use Angular's own ngDisabled directive instead of writing your own.

Service:
module.factory('GetDataService', function ($http) {
return {
getCustomers: function() {
return $http({ url: '/someurl', method: 'GET'});
}
}
});
Directive:
module.directive('disableWhenLoadingData', function (GetDataService) {
return {
restrict: 'A',
scope: {},
link: function ($scope, element, attrs) {
$scope.loadingData = true;
GetDataService.getCustomers().success(function (data) {
$scope.loadingData = false;
});
}
};
});

Generally I set $scope.loading in my controller, and my button or whatever i set ng-disabled.
In my controller:
$scope.loadData = function () {
$scope.loading = true;
$http
.get('url')
.success(function (ret) {
$scope.loading = false;
});
}
In my view:
<button ng-disabled="loading" ng-click="loadData()">{{loading? 'loading Data' : 'Submit'}}</button>

Related

Better approaches than using $broadcast to update input in directive?

Currently I have a list of contacts on controller A. When I click on one of the contacts, it is broadcasting the contact info to controller B and to the datepicker directive in controller B. This is working but is there a better way to update the input on the datepicker directive?
app.directive('datePickerDirective', [function () {
return {
restrict: 'AE',
require: 'ngModel',
scope: {
datepickerNgModel: '=',
datepickerId: '#'
},
templateUrl: 'Content/app/directives/templates/DatePicker.html',
link: function ($scope, element, attrs, ngModel) {
$scope.$watch(function () {
ngModel.$setViewValue($scope.datepickerNgModel);
return ngModel.$modelValue;
});
$scope.$on('data-from-component-a', function (event, data) {
$('#' + $scope.datepickerId).val(data.date);
})
}
}
}]);
I would avoid using events ($broadcast) here. You can do it by using a nice factory which handles the data for your components. You did not gave any information about your datepicker and controllers, so I created an abstract example which delivers you the basic handling.
> Share data via factory between controllers - demo fiddle
View
<div ng-controller="MyCtrl">
<button ng-click="publishData()">
Publish data
</button>
<button ng-click="resetData()">
Reset data
</button>
</div>
<div ng-controller="MyOtherCtrl">
<my-directive my-model="data.getData()"></my-directive>
</div>
AngularJS application
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope, myFactory) {
$scope.publishData = function() {
myFactory.publishData();
}
$scope.resetData = function() {
myFactory.resetData();
}
});
myApp.controller('MyOtherCtrl', function($scope, myFactory) {
$scope.data = myFactory;
});
myApp.directive('myDirective', function () {
return {
restrict: 'E',
template: '{{myModel}}',
scope: {
myModel: '='
},
link: function (scope, element, attrs) {
scope.$watch('myModel', function (newValue, oldValue) {
console.log(newValue);
// $('#' + $scope.datepickerId).val(newValue);
});
}
}
});
myApp.factory('myFactory', function() {
return {
contactInfo: '',
publishData: function() {
this.contactInfo = 'Sdfsdfsdf';
},
resetData: function() {
this.contactInfo = null;
},
getData: function () {
return this.contactInfo;
}
}
});

Angular directive does not update when $http completes

I'm having trouble getting a directive to update after a $http completes. The two solutions I've tried are setting a flag $scope.ready to true and using with ngIf on a parent container and using $scope.$watch() for my data object. The flag doesn't seem to work, though the element.replaceWith('<h1>test</h1>'); does seem to work, just both newVal and oldVal are undefined.
<div ng-if="ready">
<puzzle data="data"></puzzle>
</div>
//function
function myCtrl($scope, $http){
$scope.ready = false;
$scope.data = {};
$http({
method: 'GET',
url: './app/data/test1.json'
})
.then(function(res){
$scope.ready = true;
$scope.data = res.data;
console.log($scope.data);
//tried $scope.$apply() here, no success
}, function(){
console.error('err', arguments);
})
}
//directive
function myDirective(){
return {
restrict: 'E',
scope: {
data: '=',
ready: '='
},
link: function(scope, element, attrs){
scope.$watch('data',function(newVal, oldVal){
console.log(scope, element, attrs);
}, true);
element.replaceWith('<h1>test</h1>'); //this prints out
}
};
}

Controller 'alertForm', required by directive 'loginForm', can't be found! in angularjs

Controller 'alertForm', required by directive 'loginForm', can't be
found!
angular.module('jobsApp')
.directive('alertForm', function () {
return {
templateUrl: 'app/directives/alert/alertForm.html',
restrict: 'E',
scope: {
topic: '=topic',
description: '=description'
}
}
})
.directive('loginForm', function() {
return {
templateUrl: 'app/directives/loginForm/loginForm.html',
restrict: 'E',
require: '^alertForm',
scope: {
successCallback: '&',
errorCallback: '&',
emailField: '='
},
link: function (scope, element, attrs, alertFormModelCtrl) {
scope.alertFormModel = alertFormModel
},
controller: function ($rootScope, $scope, authenticationService) {
$scope.loginFormData = {};
$scope.inProgress = false;
$scope.onLogin = function (form) {
if (form.$valid) {
$scope.inProgress = true;
authenticationService.loginUser('password', $scope.loginFormData).then(function () {
$scope.inProgress = false;
}, function (err) {
$scope.inProgress = false;
if (err.message) {
//$scope.alertFormCtrl.topic = "asdffasfd";
alert(err.message);
}
});
}
}
}
};
});
Your directive requires the alertForm controller to be present in the scope of the loginForm. You'll either have to add it to the current scope. Or prefix the requirement with a ^ to search in the parent scope.
From https://docs.angularjs.org/guide/directive:
The myPane directive has a require option with value ^myTabs. When a directive uses this option, $compile will throw an error unless the specified controller is found. The ^ prefix means that this directive searches for the controller on its parents (without the ^ prefix, the directive would look for the controller on just its own element).

How to call my own function inside an Angular Directive?

I'd like to call "myFunc()" inside my angular directive, how might I do this?
myApp.directive("test", function () {
return {
restrict: 'A',
template: "<div class='box'></div>",
myFunc: function() {
console.log('myFunc');
},
link: function ($scope, element, attrs) {
element.bind('click', function () {
myFunc(); //<------------- doesn't work
});
}
} // of return
});
You can't define the function as a property of your return value in your call to directive. It either needs to be defined before your return:
myApp.directive('test', function() {
var myFunc = function() {
console.log('myFunc');
};
return {
restrict: 'A',
template: '<div class="box"></div>',
link: function($scope, element, attrs) {
element.bind('click', myFunc);
}
};
};
Or the same way inside of your link function.
Just to play around :)
var app = angular.module('myApp', []);
app.controller('MainController',function() {
});
app.directive('one', function() {
return angular.extend({}, app.directive, {myfunct:function(){
alert('hello');
}});
});
app.directive('two', function(oneDirective) {
return {
link:function($scope,$element){
console.log(oneDirective[0].myfunct)
$element.on('click',oneDirective[0].myfunct);
}
};
});
or use the method binding "&":
app.directive('myDir', function() {
return {
scope: {
callback: "&"
},
link:function($scope,$element){
element.bind('click', function () {
$scope.evalAsync(function() {
$scope.callback({param1: value, param2: value2});
})
});
}
};
});
Usage:
<my-dir callback="myControllerMethod(param1, param2)"></my-dir>

Angularjs - Call Directive after ng-init function completes

I am trying to call a Function in ng-init i my html file.
That function makes a API call and gives the data. I assigned that data to a scope variable and pass that scope variable to directive.
Controller is hitting first. But before APIi call completes directive got hitted. So the scope variable which i am passing to controller is as undefined.
App.directive('foldertree', function () {
return {
restrict: 'A',
scope: {
'inputfromapicall': '=',
'fileName': "="
},
link: function (scope, element, attrs, ngModelCtrl) {
return $timeout(function() {
$('#divid').fileTree({
root: scope.inputfromapicall, //undefined
script: '/project/current/source/data/jqueryFileTree.jsp',
expandSpeed: 1,
collapseSpeed: 1,
multiFolder: false
}, function (file) {
scope.fileName = file;
scope.$apply();
});
});
}
};
});
Above is my directive code
Sorry for posting the vague question.Hope some one help me with the fix.
As MajoB mentioned in comment scope.$watch done the trick. Here is my updated directive code.
automateOnApp.directive('foldertree', ['$timeout', function($timeout){
return {
restrict: 'A',
scope: {
'inputfromapicall': '=',
'fileName': "="
},
link: function (scope, element, attrs, ngModelCtrl, controller) {
scope.fileName = '';
return $timeout(function() {
scope.$watch(function () {
return scope.inputfromapicall;
}, function(newVal) {
if(!angular.isUndefined(scope.inputfromapicall)){
$('#divid').html('');
$('#divid').fileTree({
root: newVal,
script: '/project/current/source/data/jqueryFileTree.jsp',
expandSpeed: 1,
collapseSpeed: 1,
multiFolder: false
}, function (file) {
scope.fileName = file;
scope.$apply();
});
}
});
});
}
};
}]);
Hope it helps someone in Future

Categories