ng-repeat with custom directive throwing error - javascript

I am creating a custom directive in a controller and calling it in ng-repeat as follows:
HTML:
<div ng-controller="TestCtrl">
<div ng-repeat="page in pages">
<custom
load-data="loadData = fn">
</custom>
</div>
</div>
JS:
Test directive is as follows:
scope: {
loadData: "&"
}
controller: ['$scope', '$element', '$timeout', '$filter', function ($scope, $element, $timeout, $filter) {
$scope.loadData({ fn: function(data) {
//Data calc.
}});
}
I am calling loadData from TestCtrl as follows:
App.controller('TestCtrl', function($scope, $http, $timeout, $rootScope) {
$scope.loadData(data);
}
In TestCtrl scope, loadData function is present if ng-repeat is not used and works fine but gives error as undefined is not a function at line where $scope.loadData(data) is called when ng-repeat is used.
Thanks in Advance

The controller of your directive is not correct, It's syntax is
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }
$timeout, $filter should come after $attrs and $transculde. You need to include both even if you are not using it
Even after above changes, if there is still an issue, then we can check further, but the above has to be fixed or else you wont be able to use $timeout and $filter

Related

Dynamic loading Angular Controller

I am trying to load controllers dynamically using ocLazyLoad :
$ocLazyLoad.load('./ctrls/login.js');
But am getting this error saying:
The controller with the name 'loginCtrl' is not registered.
angular.module('optimusApp')
.controller('loginCtrl', function ($scope, $rootScope, $location, $http) {});
app.js
angular.module("optimusApp", ['ngRoute', 'oc.lazyLoad']);
angular.module('optimusApp')
.controller('globalCtrl', function ($rootScope, $location, $http, $routeParams, $ocLazyLoad) {
$ocLazyLoad.load('./ctrls/login.js');
});
I made it work by using ng-if
app.js
var optimusApp = angular.module("optimusApp", ["ngRoute", "oc.lazyLoad"])
.controller("globalCtrl", function ($rootScope, $location, $http, $routeParams, $ocLazyLoad) {
$ocLazyLoad.load("./js/app/login.js").then(function() {
console.log("loginCtrl loaded");
$rootScope.loginActive = true;
}, function(e) {
console.log("error");
});
});
login.js
optimusApp.controller('loginCtrl', function ($scope, $rootScope, $location, $http) {
});
HTML
<div ng-if="loginActive" ng-controller="loginCtrl">
</div>
Basically you will get the "registration error" if your ng-controller is in the page before you have the JS loaded.
So the ng-if is a solution, or I see you have ngRoute. So you could set ocLazyLoad to load the controller when entering a specific state.

AngularJS - controller and factory - where am I going wrong at include/inject functions?

I'm new to Angular and cannot pinpoint where I am going wrong. I'm just trying to simply inject my factory into my controller, reference said: "Cannot read property 'validar' of undefined". I have two files, ServiceUtil.js where have a service and CentroCustoCtrl.js where I'm trying to use service's function.
The function at ServiceUtil.js:
(function () {
'use strict';
angular.module('Services', [])
.service('ValidarFormulario', [function () {
this.validar = function (form) {
var valido = true;
//code
}
return valido;
}
}]);
})();
And CentroCustoCtrl.js
(function () {
'use strict';
var app = angular.module("start", ['AxelSoft', 'ngLocalize',
'ngLocalize.Config', 'mvComponentes','Services'])
.value('localeConf', {
basePath: '../Scripts/Locales', ...
...
});
app.controller('CentroCustoCtrl', ['$scope', '$http', 'ValidarFormulario', function ($scope, $http, $rootScope, $timeout, ValidarFormulario) {
$scope.Salvar = function () {
if (ValidarFormulario.validar(document.getElementsByTagName('input'))) { ...// Cannot read property 'validar' of undefined
);
I tried with factory , but not worked too:
angular.module('Services', [])
.factory('ValidarFormulario', [function () {
return{
validar : function (form) {
var valido = true;
//code
}
}
return valido;
}
}
}]);
})();
Please, I appreciate any help you can provide.
The problem is you had wrong dependency sequence inside DI inline array, basically they are mismatching in number and their sequences
app.controller('CentroCustoCtrl', ['$scope', '$http', 'ValidarFormulario',
//removed $rootScope, $timeout which wasn't used.
function ($scope, $http, ValidarFormulario) {
OR either way you could just add the dependency inside array, if they are really gonna used inside controller like below
app.controller('CentroCustoCtrl', ['$scope','$http','$rootScope','$timeout','ValidarFormulario',
function ($scope, $http, $rootScope, $timeout, ValidarFormulario) {
Just change the below line of code
app.controller('CentroCustoCtrl', ['$scope', '$http', 'ValidarFormulario', function ($scope, $http, $rootScope, $timeout, ValidarFormulario) {
to
app.controller('CentroCustoCtrl', ['$scope', '$http', '$rootScope', '$timeout', 'ValidarFormulario', function ($scope, $http, $rootScope, $timeout, ValidarFormulario) {
This should work.
Well, also I've saw that your controller injections are wrong. You have:
App.controller('CentroCustoCtrl', ['$scope', '$http', 'ValidarFormulario', function ($scope, $http, $rootScope, $timeout, ValidarFormulario)
And you should have:
app.controller('CentroCustoCtrl', ['$scope', '$http', '$rootScope', '$timeout', 'ValidarFormulario', function ($scope, $http, $rootScope,$timeout, ValidarFormulario)
Injectors on "[ ]" must mach with function parameters.
When you set a module the syntax is:
angular.module('Services', [ here injections ])
But when you get a module to use it, syntax must be:
angular.module('Services')

Assigning data in link function in Angular

I am currently building an app. My view has been minified to this for presentation purposes:
<div class='reviews' ng-repeat="review in reviews">
<div><ratestar></ratestar></div>
</div>
I also have a directive that I built:
angular.module('LiveAPP.artist',[])
.controller('artistCtrl', ['$scope', '$http', '$location', 'dataFactory', '$routeParams', artistCtrl])
.directive("ratestar", function() {
return {
restrict: "E",
scope: {},
template: "<div id='rateYo'></div>",
link: function( scope, ele, attrs ) {
var $rateYo = $(ele).rateYo({
rating:***VARIES ACCORDING TO REVIEW***
});
}
};
});
function artistCtrl($scope, $http, $location, dataFactory, $routeParams){
$scope.reviews = [{num_of_stars:1},...,{num_of_stars:3}]
}
Essentialy I want the rating in rateYo({}) to be the num_of_stars from $scope.reviews. So when ng-repeat is run it takes each object from from $scope.reviews and assigns num_of_stars to rating. Anyone have any idea on how to tackle this? I had a feeling that adding class=$index to <ratestar></ratestar> might work, but it didn't.

AngularJS - State name passed into controller doesn't work

I'm new to angular and I can't figure out why this isn't working.
When I call {{$state.current.name}} in my view it works perfectly fine, but as soon as I try to pass it to my controller, the state gets "lost".
Here is my setup:
Module:
angular.module('app', ['ui.router'])
.run(function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
})
//followed by boilerplate ui router setup
View:
<home-nav-bar></home-nav-bar>
Directive:
angular.module('app')
.directive('homeNavBar', function () {
return {
restrict: 'E',
templateUrl: 'homeNavBarView.html',
controller: 'navCtrl'
};
})
})();
Controller:
angular.module('app')
.controller('navCtrl', function ($state, $scope) {
alert($state.current.name); //returns empty
});
})();
At this point I am clueless as to why I can get the state name in the view but not in my controller..
Well, ui-router docs say you can access current state's config object using the current property of $state, so there is absolutely no need to attach anything to $rootScope. I have just tested something along the lines of (simplified a bit for readability):
angular.module('myApp')
.controller('SomeCtrl', function ($scope, $state) {
console.log($state.current);
});
The result in Chrome console is:
Object {url: "/some", templateUrl: "app/some.html", controller: "SomeCtrl", name: "some"}
So as you can see all information should be available along with the name.

Angularjs: Can I have my directive run after controller API callback

first time asker. Apologies if my jargon isn't quite right I'm new to angularjs
I have a controller which gets a list of products with a HTTP call
contractManagementControllers.controller('PriceBandsCtrl', ['$scope', '$routeParams', '$http', '$location',
function ($scope, $routeParams, $http, $location)
{
$http.get('products').success(function (products)
{
$scope.productList = products
})
}
And a directive which I would like to have access to that product list.
contractManagementControllers.directive("priceBands",function($http)
{
return {
scope: true,
restrict: 'AE',
replace: 'true',
templateUrl: 'Partials/PriceBand.html',
link: function ($scope, ele, attrs, c)
{
// use $scope.productList
}
});
My issue is with the order in which things happen. The controller function runs first, followed by the directive link function, followed by the callback which sets the product list. As such $scope.productList is undefined in the directive link function and gives an error
Is there a way to force the link function to wait until the callback has completed?
Set default value to productList in order not get error about undefined variable
contractManagementControllers.controller('PriceBandsCtrl', ['$scope', '$routeParams', '$http', '$location',
function ($scope, $routeParams, $http, $location)
{
$scope.productList = [];
$http.get('products').success(function (products)
{
$scope.productList = products
})
}
and then watch for changes of the productList in directive:
contractManagementControllers.directive("priceBands",function($http)
{
return {
scope: true,
restrict: 'AE',
replace: 'true',
templateUrl: 'Partials/PriceBand.html',
link: function ($scope, ele, attrs, c)
{
$scope.watch('productList', function(newValue, oldValue) {
//Perform here if you need
});
}
});
no need of waiting for callback in angularjs. just put the $scope.productList=[]; in your controller as first line. it will not give undefined to directive.
In your directive link function just write the $watch function to watch changes in element.

Categories

Resources