AngularJS: Error: No controller: form - angularjs

HTML:
<div ng-app="my-app" ng-controller="AppController">
<ng-form name="myform">
<gtux-el></gtux-el>
</ng-form>
</div>
JS
var app = angular.module('my-app', [], function () {
})
app.controller('AppController', function ($scope) {
})
app.directive('gtInputMsg', ['$compile', '$interpolate', '$log', function($compile, $interpolate, $log) {
function link($scope, element, attrs, ctrls) {
var modelCtrl = ctrls[0], formCtrl = ctrls[1], msgCtrl = ctrls[2];
element.on('click', function() {
console.log('gt-input-msg:click', element)
});
};
return {
require : ['ngModel', '^form', 'gtInputMsg'],
link : link
};
}]);
app.directive('gtuxTextfield', ['$compile', '$timeout', '$log', function($compile, $timeout, $log) {
return {
restrict : 'E',
template : '<input type="text" name="field" gt-input-msg ng-model="fieldvalue" />',
replace : true
};
}]);
app.directive('gtuxEl', ['$compile', '$timeout', '$log', function($compile, $timeout, $log) {
function link($scope, $element, attrs, ctrl) {
//here compile is used because in my use case different elements are used based on some option values. A service provides the template to be used based on a key
var $cr = $compile('<gtux-textfield></gtux-textfield>')($scope);
$($cr).appendTo($element);
}
return {
restrict : 'E',
link : link,
transclude : true
};
}]);
Error
Error: No controller: form
at Error (<anonymous>)
at getControllers (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:4278:19)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:4284:24
Demo: Fiddle
As far I can see there is a ng-form element at the top of the hierarchy which should provide the from controller to the gtInputMsg directive.
How can this be rectified?

You're compiling the <gtux-textfield> element without it being under the form in the DOM as you haven't appended it yet. Try:
var $cr = $('<gtux-textfield></gtux-textfield>').appendTo($element);
$compile($cr)($scope);
In your gtuxEl link function.
Demo: Fiddle

Related

Custom directive Attribute

In my custom directive im getting attributes values, in my case it could be numbers or arrays, but in my directtive im getting a string array (ex: "[1,2]".
How can i get my array in the attribute not being a string?
view:
<div my-directive to=[1,2]
directive:
angular.module('myApp')
.directive('myDirective',
[
'$http', '$q','$uibModal',
dir
]);
function dir($http, $q, UserService, $uibModal) {
return {
restrict: 'A',
link: function($scope, element, attrs, controller) {
element.on( 'click', function( evt ){
console.log(attrs.to);
});
}
};
}
Try following approach:
On view (init the directive & set the directive param)
<div ng-app='demo'>
<demo-directive to-val='[1,2,3,4,5]'></demo-directive>
</div>
On the directive
var demo = angular.module('demo', []);
demo.directive('demoDirective', function($parse) {
return {
restrict: 'E',
template: '<div ng-repeat="val in toVal">{{val}}</div>',
link: function (scope, element, attrs, controller) {
// parse the attribute array to a scope params
scope.toVal = JSON.parse(attrs.toVal);
}
}
});

Call a function after the directive is loaded angularjs

I have a isolated directive, my controller looks like:
app.controller('ZacksController', ['$scope', '$http', 'ngDialog', '$timeout', function($scope, $http, ngDialog, $timeout){
//some code here
}]);
The HTML in the file looks like:
<div class="income-older-block" ng-show="selectedAge!=1">
<income-form></income-form>
</div>
I have a directive in related HTML folder,
app.directive("incomeForm", ['$timeout', function ($timeout) {
function link($scope) {
var hello = function () {
alert("1");
}
$timeout(hello, 0);
}
return {
restrict: 'E',
templateUrl: "app/zacks/your-income/income-form/income-form.html",
link: link,
controller: function ($scope, $timeout) {
$scope.$watch("zacks.AgeRet.value",function(newValue,OldValue,scope){
if (newValue){
alert((newValue));
}
});
}
}
}]);
I want to alert after I load the directive in the page, the alert appears at initial page itself. May I know what to do?
The actual problem is I'm using a rz-slider and want to initialize it once the directive is loaded to DOM., as its not taking the values provided. Is there any other approach for this problem?
<rzslider rz-slider-model="zacks.AgeRet.value" rz-slider-floor="zacks.AgeRet.floor" rz-slider-ceil="zacks.AgeRet.ceil"></rzslider>
In case if the timeout works, I'm planning to initialize something like this:
$timeout(function () {
$scope.$broadcast('rzSliderForceRender');
});
UPDATE
Added a controller in the directive, so now I'm able to get the value when I move the slider, but still not able to initialize the value of the slider.
I kind of found 2 solutions for these kind of problems, but still not serving the purpose of what I really need with rz-slider.
Solution 1
HTML:
<div ng-controller="ZacksController">
<after-render after-render="rzSliderForceRender">element</after-render>
</div>
JS:
var app = angular.module('myApp',[]);
app.directive('afterRender', ['$timeout', function ($timeout) {
var def = {
restrict: 'E',
link: function (scope, element, attrs) {
$timeout(scope.$eval(attrs.afterRender), 0); //Calling a scoped method
}
};
return def;
}]);
app.controller('ZacksController', ['$rootScope', '$scope', '$http', ' $timeout', function($rootScope, $scope, $http, $timeout){
$scope.rzSliderForceRender = function()
{
alert('Fired!');
};
}]);
Solution 2
HTML:
<div class="income-older-block" ng-show="selectedAge!=1">
<income-form></income-form>
</div>
JS:
app.controller('ZacksapiController', ['$rootScope', '$scope', '$http', 'ngDialog', '$timeout', 'dataService', function($rootScope, $scope, $http, ngDialog, $timeout, dataService){
$scope.$watch('selectedAge', function(newValue, oldValue) {
if (newValue !== oldValue) {
$timeout(function() {
alert("reCalcViewDimensions");
$scope.$broadcast('rzSliderForceRender'); // This is not working, but alert works.
}, 0);
}
});
Update:
Triggered the window resize event inside the $timeout, but this would be a temporary hack. Would be great if someone help me out with the real approach to solve the problem.
$timeout(function() {
window.dispatchEvent(new Event('resize'));
$scope.$broadcast('rzSliderForceRender');
}, 0);

Event not triggering for runtime controls in angularjs directive

Created a directive using AngularJS. The directive displays a runtime (dynamic) controls but it is not triggering an event from controller. Can any one help me.
Note: used compile in directive too.
The plnkr link is given below.
module.controller('controllerOne', ['$scope', function ($scope) {
$scope.AddClickButton = function () {
alert("Button Clicked");
};
}]);
module.directive('directiveOne', ['$compile', function ($compile) {
return {
restrict: 'E',
scope: {
data: '='
},
link: function ($scope, $element, $attrs) {
var btnhtml = '<button type="button" ng-click="AddClickButton()">Click Me</button>';
var temp = $compile(btnhtml)($scope);
$element.append(temp);
}
};
}]);
HTML
<form name="form1" >
<directive-one data="dataOne"></directive-one>
</form>
Plunkr
You should be passing AddClickButton method reference to directive using &(expression binding) as directive has been using isolated scope. So it don't have any idea about parent scope directly.
Markup
<form name="form1" >
<directive-one data="dataOne" click-action="AddClickButton()"></directive-one>
And then call that method from directive using that clickAction isoalted scope prop.
Directive
module.directive('directiveOne', ['$compile', function($compile) {
return {
restrict: 'E',
scope: {
data: '=',
clickAction: '&'
},
link: function($scope, $element, $attrs) {
var btnhtml = '<button type="button" ng-click="clickAction()">Click Me</button>';
var temp = $compile(btnhtml)($scope);
$element.append(temp);
}
};
}]);
Forked Plunkr
You can use this version http://plnkr.co/edit/9QCpAQUhOKZ3NtU1rfhY
link: function ($scope, $element, $attrs) {
$scope.AddClickButton = function() {
alert($scope.text);
}
}
and remove the function from the controller

Upgraded to 1.4.1 and now: Argument 'SearchPopover' is not a function, got undefined

First I had to fix the following:
controller: SearchPopover
Changed to
controller: 'SearchPopover as spop',
My Directive & Controller below, I've tried:
.module('searchPopoverDirectives', ['searchPopoverDirectives.SearchPopover']) but then I get an undetailed error Uncaught Error:
(function() { "use strict";
angular
.module('searchPopoverDirectives', [])
.directive('searchPopover', directive);
function directive() {
var directive = {
templateUrl : 'popovers/searchPopover/searchPopover.html',
restrict: "E",
replace: false,
bindToController: true,
controller: 'SearchPopover as spop',
// controllerAs: 'spop',
link: link,
scope: {}
};
return directive;
function link(scope, element, attrs) {}
}
SearchPopover.$inject = [
'$scope',
'$rootScope',
'$timeout',
'ApiFactory',
'ScopeFactory',
'TagFactory',
'TickersSelectFactory',
'TagDetailsFactory',
'ViewFactory'];
function SearchPopover(
$scope,
$rootScope,
$timeout,
ApiFactory,
ScopeFactory,
TagFactory,
TickersSelectFactory,
TagDetailsFactory,
ViewFactory) {
Markup
<div ng-controller="SearchPopover" ng-class="{'display-on': searchPopoverDisplay}" class="search-popover">
....

ui-select2 and ng-required

I'm having problems using require/ng-require with the ui-select2 component. I wrapped the ui-select2 in a custom directive for reasons of reusability, but can't get the required to work with it.
This is the plunker: http://plnkr.co/edit/2NaGvDWoEw14BN2few9W?p=preview
Tried without the directive and it's working: http://plnkr.co/edit/uE698iFcUNnsYVF2fkOO?p=preview
The Problem was that angular dosn't support dynamic form element:
Issue #1404 https://github.com/angular/angular.js/issues/1404
Workaround (till 1.3 is out):
app.config(['$provide', function($provide) {
$provide.decorator('ngModelDirective', ['$delegate', function($delegate) {
var ngModel = $delegate[0], controller = ngModel.controller;
ngModel.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
var $interpolate = $injector.get('$interpolate');
attrs.$set('name', $interpolate(attrs.name || '')(scope));
$injector.invoke(controller, this, {
'$scope': scope,
'$element': element,
'$attrs': attrs
});
}];
return $delegate;
}]);
$provide.decorator('formDirective', ['$delegate', function($delegate) {
var form = $delegate[0], controller = form.controller;
form.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
var $interpolate = $injector.get('$interpolate');
attrs.$set('name', $interpolate(attrs.name || attrs.ngForm || '')(scope));
$injector.invoke(controller, this, {
'$scope': scope,
'$element': element,
'$attrs': attrs
});
}];
return $delegate;
}]);
Source: http://jsfiddle.net/Thinkscape/23RPt/

Resources