Angular Unknown provider. Netsted controllers - angularjs

I cannot work out how to call a method in another angular controller.
On the webpage there is another angular app. I want to use some of the functionality from the other app. As soon as i add the other controller to my html I get this error when the page loads:
Unknown provider: documentsServiceProvider <- documentsService <- documentActionsController
My code:
angular.module('myApp', [])
.controller("documentActionsController", SomeNameSpace.DocumentActionsController)
.controller('myController', function ($scope) {
Markup
<div id="qms-part-docApp" ng-controller="myController" >
<tr ng-repeat="fileInfo in documentList track by $index">
<a ng-controller="documentActionsController" ng-click="addToFavorites()"></a></td>
I want to call a method on this documentActionsController (TypeScript compiled)
var Controllers;
(function (Controllers) {
var DocumentActionsController = (function (_super) {
__extends(DocumentActionsController, _super);
function DocumentActionsController($scope, documentsService, basketService, favoritesService) {
var _this = this;
_super.call(this, $scope);
this.$scope = $scope;
this.documentsService = documentsService;
this.basketService = basketService;
this.favoritesService = favoritesService;
this.init = function () {
_this.$scope.addToFavorites = _this.addToFavorites;
_this.$scope.removeFromFavorites = _this.removeFromFavorites;
_this.$scope.addToBasket = _this.addToBasket;
_this.$scope.removeFromBasket = _this.removeFromBasket;
_this.$scope.markAsRead = _this.markAsRead;
_this.$scope.isItInFavorites = _this.isItInFavorites;
_this.$scope.isItInBasket = _this.isItInBasket;
_this.$scope.isItRead = _this.isItRead;
};
this.addToFavorites = function (id, title, owner, url, icon, path) {
SomeNamespace.addToFavorites(id, title, owner, url, icon, path);
};
this.removeFromFavorites = function (id, path) {
SomeNamespace.removeFromFavorites(id, path);
};
this.addToBasket = function (id, title, owner, url, icon, filename) {
SomeNamespace.addToBasket(id, title, owner, url, icon, filename);
};
this.removeFromBasket = function (id) {
SomeNamespace.removeFromBasket(id);
};
this.markAsRead = function (id, version) {
SomeNamespace.markAsRead(id, version);
};
this.isItInFavorites = function (id) {
SomeNamespace.isItInFavorites(id);
};
this.isItInBasket = function (id) {
SomeNamespace.isItInBasket(id);
};
this.isItRead = function (id, version) {
SomeNamespace.isItRead(id, version);
};
this.init();
}
DocumentActionsController.$inject = [
"$scope",
"documentsService",
"basketService",
"favoritesService"
];
return DocumentActionsController;

Register services like this,
angular.module('myApp', [])
.service("documentsService", function(){
// write code
})
.service("basketService", function(){
// write your code
})
.service("favoritesService", function(){
// write your code
})
.controller("documentActionsController", SomeNameSpace.DocumentActionsController)
.controller('myController', function ($scope) {

Related

Calling filter from different JS file in Controller

I have a controller that was residing in a separate file named as EmployeeCtrl.js. Inside this controller I have a filter called convertJsonDate to convert JsonResult date format to normal format MM/dd/yyyy hh:mm:ss.
My question now is, how do I make this filter reusable in different controller in the future? I have read that you can add your filter in a separate js file filters.js and inject it to your controller, but I don't know to implement this.
TIA
app.js
(function () {
'use strict';
angular.module('app', []);
})();
EmployeeCtrl.js
(function () {
'use strict';
var app = angular.module('app');
app.filter('convertJsonDate', ['$filter', function ($filter) {
return function (input, format) {
return (input) ? $filter('date')(parseInt(input.substr(6)), format) : '';
};
}]);
app.controller('app.EmployeeController', ['$scope', 'app.EmployeeService', function ($scope, EmployeeService) {
GetAllEmployee();
$scope.sortColumnBy = function (keyname) {
$scope.sortKey = keyname;
$scope.reverse = !$scope.reverse;
}
$scope.employee = {
employeeId: '',
firstName: '',
lastName: '',
password: '',
daysPerWeek: 0,
active: true,
departmentId: 0,
accountTypeId: 0
};
$scope.clear = function () {
$scope.employee.employeeId = '';
$scope.employee.firstName = '';
$scope.employee.lastName = '';
$scope.employee.password = '';
$scope.employee.daysPerWeek = 0;
$scope.employee.active = false;
$scope.employee.departmentId = 0;
$scope.employee.accountTypeId = 0;
};
function GetAllEmployee() {
var getEmployeeData = EmployeeService.getEmployees();
getEmployeeData.then(function (employee) {
$scope.employees = employee.data;
}, function () {
alert('Error in getting employee records');
});
};
}]);
})();
Using convertJsonDate filter
<div ng-app="app">
<div ng-controller="app.EmployeeController">
.....
<tbody>
<tr ng-repeat="e in employees | orderBy:sortKey:reverse | filter:searchKeyWord">
<td>{{e.AccountDateExpired | convertJsonDate:'MM/dd/yyyy hh:mm:ss'}}</td>
</tr>
</tbody>
....
</div>
</div>
Pastebin
Index.chtml
http://pastebin.com/aXDSmYAV
EmployeeCtrl.js
http://pastebin.com/eQhRREPy
app.js
http://pastebin.com/1GB4uhvx
It doesn't matter if they're in the same file or in different files. As long as both are in the same module, or the filter is in a module that you include in your dependencies, you will be able to use it.
I would suggest having 3 files here: one that declares your module, one for your controller(s), and one for your filter(s):
module.js
var app = angular.module('app', []);
filters.js
var app = angular.module('app');
app.filter('convertJsonDate', ['$filter', function ($filter) {
return function (input, format) {
return (input) ? $filter('date')(parseInt(input.substr(6)), format) : '';
};
}]);
controllers.js
var app = angular.module('app');
app.controller('app.EmployeeController', ['$scope', 'app.EmployeeService', function ($scope, EmployeeService) {
GetAllEmployee();
$scope.sortColumnBy = function (keyname) {
$scope.sortKey = keyname;
$scope.reverse = !$scope.reverse;
}
$scope.employee = {
employeeId: '',
firstName: '',
lastName: '',
password: '',
daysPerWeek: 0,
active: true,
departmentId: 0,
accountTypeId: 0
};
$scope.clear = function () {
$scope.employee.employeeId = '';
$scope.employee.firstName = '';
$scope.employee.lastName = '';
$scope.employee.password = '';
$scope.employee.daysPerWeek = 0;
$scope.employee.active = false;
$scope.employee.departmentId = 0;
$scope.employee.accountTypeId = 0;
};
function GetAllEmployee() {
var getEmployeeData = EmployeeService.getEmployees();
getEmployeeData.then(function (employee) {
$scope.employees = employee.data;
}, function () {
alert('Error in getting employee records');
});
};
}]);
})();
They can be reused if you are using same app
...here,
var app = angular.module('app');
you could use this filter in the same way you are using it in current controller for any other controller under this app

Directive in ng-repeat not re-processing after updating the array

I have a directive which converts certain strings into links (/) tags. I use this directive inside an ng-repeat to add links to text within a list of s. However, I refresh this data from a server which overwrites the array of the ng-repeat. The list gets updated in the DOM but the text no longer has links in it as it did when processed by the directive. How do I make the directive reprocess the text to add links?
Relevant code below
Controller HTML
<div ng-repeat="post in posts track by $index" ng-if="!post.deleted">
<div class="post wrap" ng-click="openSinglePostView(post, $index)" >
<div class="post-desc" linkify="twitter" ng-bind="post.desc"></div>
</div>
</div>
Controller JS
$scope.posts = [];
function refresh(){
$http.get(Constants.GET_POSTS_URL, {params : paramObject})
.then(function (response){
$scope.posts = [];
for(var i = 0; i < response.data.resultsArray.length; i++){
var post = new PostFactory(response.data.resultsArray[i]);
$scope.posts.push(post);
}
});
}
refresh();
Directive code
angular.module('linkify').directive('linkify', ['$filter', '$timeout', 'linkify', function ($filter, $timeout, linkify) {
'use strict';
return {
//restrict: 'A',
link: function (scope, element, attrs) {
var type = attrs.linkify || 'normal';
$timeout(function () { element.html(linkify[type](element.html()));
});
}
};
}]);
and for reference, the directive uses these filters and factories
angular.module('linkify')
.filter('linkify', function (Constants) {
'use strict';
function linkify (_str, type) {
if (!_str) {
return;
}
var _text = _str.replace( /(?:https?\:\/\/|www\.)+(?![^\s]*?")([\w.,#?!^=%&:\/~+#-]*[\w#?!^=%&\/~+#-])?/ig, function(url) {
var wrap = document.createElement('div');
var anch = document.createElement('a');
anch.href = url;
anch.target = "_blank";
anch.innerHTML = url;
wrap.appendChild(anch);
return wrap.innerHTML;
});
// bugfix
if (!_text) {
return '';
}
// Twitter
if (type === 'twitter') {
_text = _text.replace(/(|\s)*#([\u00C0-\u1FFF\w]+)/g, '$1#$2');
_text = _text.replace(/(^|\s)*#([\u00C0-\u1FFF\w]+)/g, '$1#$2');
}
return _text;
}
//
return function (text, type) {
return linkify(text, type);
};
})
.factory('linkify', ['$filter', function ($filter) {
'use strict';
function _linkifyAsType (type) {
return function (str) {(type, str);
return $filter('linkify')(str, type);
};
}
return {
twitter: _linkifyAsType('twitter'),
icon: _linkifyAsType('icon'),
normal: _linkifyAsType()
};
}])
Could the track by $index be the problem? Have you tried without it?

View doesn't get updated from Service

I am trying to display an object (songTitle) from my service. The initial state (tmp) is displayed. If I am changing the object in the service, the view doesnt get updated.
Js:
var party = angular.module("party", []);
party.run(function () {
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
});
party.service('PlayerService', function ($window) {
this.playlist = [
"https://www.youtube.com/watch?v=fnW2uLwHAas",
"https://www.youtube.com/watch?v=iPT8DA32U6U",
"https://www.youtube.com/watch?v=eGjEnfQl37s",
"https://www.youtube.com/watch?v=nFtTY2S20mI",
"https://www.youtube.com/watch?v=UmXQiPLoLTk",
"https://www.youtube.com/watch?v=PbVx85DS9zc",
"https://www.youtube.com/watch?v=ciidn3nEoiE",
"https://www.youtube.com/watch?v=sm0DgkBEnUI",
"https://www.youtube.com/watch?v=J2OCSWF7sAw",
"https://www.youtube.com/watch?v=y_-giRHtuv8",
"https://www.youtube.com/watch?v=iPT8DA32U6U",
"https://www.youtube.com/watch?v=eGjEnfQl37s",
"https://www.youtube.com/watch?v=nFtTY2S20mI",
"https://www.youtube.com/watch?v=UmXQiPLoLTk",
"https://www.youtube.com/watch?v=PbVx85DS9zc"
];
this.player = {};
this.pbTimer = null;
this.songTitle = "tmp";
$window.onYouTubeIframeAPIReady = function () {
this.player = new YT.Player('ytplayer', {
height: '100',
width: '100',
videoId: 'ciidn3nEoiE',
events: {
'onReady': onPlayerReady
}
});
}
function onPlayerReady() {
console.log("db ready");
songTitle = player.getVideoData().title;
console.log(songTitle);
}
this.playVideo = function (url) {
console.log("db playVideo " + url);
player.loadVideoById(url.split("watch\?v=")[1], 0, "large");
console.log(player);
}
});
party.controller("FrontController", function ($scope) {
$scope.front = {};
$scope.front.title = "PARTY";
});
party.controller("PartyController", ['$scope', 'PlayerService', function ($scope, PlayerService) {
$scope.party = {};
$scope.party.title = "PARTY";
Sortable.create(playlist, { /* options */ });
$scope.playlist = PlayerService.playlist;
$scope.playVideo = function (url) {
PlayerService.playVideo(url);
}
$scope.songTitle = PlayerService.songTitle;
}]);
HTML
<body ng-app="party">
<div ng-controller="PartyController" class="container-fluid">
...
<p id="playertitle">{{songTitle}}</p>
...
Log:
db ready
Blackmill Feat. Veela - Life (Full Version)
The problem is in your onPlayerReady function. The line songTitle = player.getVideoData().title; doesn't set songTitle on your service, but rather on the global scope, which is the window object. Simply using this.songTitle won't help either, because this doesn't refer to your service too in the scope of onPlayerReady.
The easiest solution would be to save a reference to your service outside of onPlayerReady and then use it to assign songTitle:
var self = this;
function onPlayerReady() {
console.log("db ready");
self.songTitle = player.getVideoData().title;
console.log(self.songTitle);
}
Still, this is not enough. Because you change songTitle from outside the Angular world (the Youtube player callbacks), you need to call $scope.$apply to notify Angular something has changed.
For that, you need to inject $rootScope into your service:
party.service('PlayerService', function ($window, $rootScope)
and change songTitle using $rootScope.$apply:
var self = this;
function onPlayerReady() {
console.log("db ready");
$rootScope.$apply(function() {
self.songTitle = player.getVideoData().title;
console.log(self.songTitle);
});
}

Angular loading template manualy and then concatenate with another one

I need to load some template from path and concatenate with another one example:
(function (module) {
var modalDialog = function (modal) {
return function (item, template, header) {//template as parameter
var inlineTMp = "<div>inline template</div>";//this template
var concatTemplate = template + inlineTMp;//pseudo code
var modalInstance;
var options = {
template: concatTemplate,
controller: function () {
this.title = header || 'Dialog';
this.data = angular.copy(item);
this.noClicked = function() {
modalInstance.dismiss('cancel');
};
this.yesClicked = function (itemData) {
modalInstance.close(itemData);
};
},
controllerAs:"model"
};
modalInstance = modal.open(options);
return modalInstance.result;
}
}
module.factory("modalDialog", ['$modal', modalDialog]);
})(angular.module("common"));
so how do i download a template then concatenate with another and send to service.

Variables between factories in angular.js

I'm currently learning angular and have hit a roadblock.
The second factory (shown below) makes an http request like this: http://example.com/api/get_post/?post_id=7129&callback=JSON_CALLBACK');
I want the post ID to be a variable. So depending on which blog title is clicked, I can pass the correct variable into that http request.
In other words, I guess I want to take a result from the first factory (blogAPIservice) and use it in the second factory.
Makes sense??
<!-- FACTORIES -->
angular.module('blogApp.services',[])
.factory('blogAPIservice',function($http) {
var blogAPI = [];
var blogs = $http.jsonp('http://example.com/api/get_recent_posts/?count=10&callback=JSON_CALLBACK');
blogs.success(function(data) {
$.each(data.posts, function(i, blog) {
var fromNow = moment(blog.date).fromNow();
blogAPI.push({
url: blog.url,
title: blog.title,
excerpt: blog.excerpt,
date : fromNow,
id: blog.id
})
});
});
var factory = {};
factory.getBlogs = function () {
return blogAPI;
};
return factory;
})
.factory('singlePostService',function($http) {
var singleAPI = [];
var postID = '7129';
var singlePost = $http.jsonp('http://example.com/api/get_post/?post_id=7129&callback=JSON_CALLBACK');
singlePost.success(function(data) {
singleAPI.push({
title: data.post.title,
content: data.post.content
})
});
var factory = {};
factory.getSinglePost = function () {
return singleAPI;
};
return factory;
})
And here are the controllers:
angular.module('blogApp.controllers', [])
.controller('resultsController',function($scope, blogAPIservice) {
$scope.keywordFilter = null;
$scope.blogs = [];
init();
function init() {
$scope.blogs = blogAPIservice.getBlogs();
}
function grabID() {
$(this).attr('rel');
}
})
.controller('singlePostController',function($scope, singlePostService) {
$scope.keywordFilter = null;
$scope.singlePost = [];
init();
function init() {
$scope.singlePost = singlePostService.getSinglePost();
}
})
And finally the markup:
<li ng-repeat="blog in blogs">
{{ blog.title }}
</li>
You can inject the first service into the second one like this:
.factory('singlePostService',function($http, blogAPIservice) {
//Do something with blogAPIservice
}
For more information about depenency injection read the docs

Resources