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
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;
}
}
});
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!
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).
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>
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