I must add I am working on Sharepoint 2013, visual web part. my ascx:
<%@ Control Language="C#" Inherits="SharePoint.BLL.UserControls.VODCatalog, SharePoint.BLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=81fc048468441ab3" %>
<%@ Register TagPrefix="SPWP" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<div ng-app="VODCatalogModule">
<div class="wrapper" ng-view="">
</div>
</div>
My JS:
var VODCatalogModule = angular.module('VODCatalogModule', []);
var testWPDefinedView = 'TopLevelView';
VODCatalogModule.config(function ($routeProvider) {
$routeProvider.when('/TopLevelView', { controller: 'VODCatalogController', templateUrl: '/_catalogs/masterpage/html/VODCatalog_TopLevelView.html' })
.when('/LowLevelView', { controller: 'VODCatalogController', templateUrl: '/_catalogs/masterpage/html/VODCatalog_LowLevelView.html' })
.otherwise({ redirectTo: '/' + testWPDefinedView });
});
function VODCatalogController($scope, $http) {
$scope.VODCatalogLevel = 1;
$scope.BreadCrumbs = [];
$scope.MainCatalog = [];
$scope.NavCatalog = [];
$scope.crumbsVisible = $scope.BreadCrumbs.length == 0 ? "hidden" : "";
var getVODCatalogData = function (PARENT_VOD_CATALOG_GK, vodLevel) {
var url = "VODCatalogHandler.ashx?action=GetVODCatalogData&vodLevel=" + vodLevel;
if (PARENT_VOD_CATALOG_GK)
url += "&PARENT_VOD_CATALOG_GK=" + PARENT_VOD_CATALOG_GK;
$http.get(url, { cache: true })
.success(function (data, status, headers, config) {
setVODCatalogData(data, vodLevel);
}).error(function (data, status, headers, config) {
alert('ERROR in VODCatalogDataService get');
});
};
var setVODCatalogData = function (data, vodLevel) {
$scope.BreadCrumbs = data;
$scope.MainCatalog = data;
$scope.NavCatalog = data;
};
$scope.catalogItemClick = function (catalogItem) {
getVODCatalogData(catalogItem.VOD_CATALOG_GK, ++$scope.VODCatalogLevel);
};
getVODCatalogData(null, $scope.VODCatalogLevel);
}
VODCatalogModule.controller("VODCatalogController", VODCatalogController);
My view (VODCatalog_TopLevelView.html):
<section class="zebra brightBGcolor">
<div class="catalog">
<div class="centerPage">
<div class="pageTitle withBreadCrumbs">
<h3>VOD</h3>
<ul class="breadCrumbs {{ crumbsVisible }}">
<li>
<a href="#">VOD</a>
</li>
<li ng-repeat-start="crumb in BreadCrumbs">
<span> </span>
</li>
<li ng-repeat-end>
<a href="#">{{ crumb.NAME }}</a>
</li>
</ul>
</div>
<ul class="list inRow4 clearfix">
<li ng-repeat="catalogItem in MainCatalog" ng-click="catalogItemClick(catalogItem)">
<a class="box" href="#">
<img src="{{ catalogItem.MEDIA_URI_Complete}}" alt="">
<div class="textContainer">
<h4>{{ catalogItem.NAME }}</h4>
</div>
</a>
</li>
</ul>
</div>
</div>
</section>
At the start all looks great, it loads the 1st ajax call with all the pics and data.
Then when I click at one of the li's with the ng-click the 2nd ajax gets executed twice, once it gets the right data and immediately after it calls itself again with the initial call of getVODCatalogData(null, $scope.VODCatalogLevel); and brings back the old view.
When I tried to put something in module.run it also runs twice, can it help?
I would appreciate any hint and help as it is my 1st time with angular.
thx! ariel
EDIT: some more info - I put a log at the beginning of the controller and after the click the controller gets initialized again
2 Answers 2
If the controller is specified in the $routeProvider and in the HTML template it will get create once for each declaration.
Comments
2nd Answer, the technical answer is that the $routeProvider caused it, i dont know why but when i change my "master" html to this:
<div ng-app="VODCatalogModule" ng-controller="VODViewsController" ng-switch on="templateUrl">
<div class="wrapper" ng-switch-when="TopLevelView" ng-include="'/_catalogs/masterpage/html/VODCatalog_TopLevelView.html'" ng-controller="VODCatalogController"></div>
<div class="wrapper" ng-switch-when="LowLevelView" ng-include="'/_catalogs/masterpage/html/VODCatalog_LowLevelView.html'" ng-controller="VODCatalogController"></div>
</div>
the controller finally was created only once. the conclusion is that if you gonna work with the $routeProvider then its only good for basic routing, anything more complex require work.
the most famous article and example for that is Nested Views Routing-And Deep Linking With AngularJS who created a wonderful architecture, while my attempt that will be included in my blog is something more dynamic, i will try to read the params in the factory.
1st Answer:
found the solution!
i was not using MVC architecture.
the controller is SUPPOSED to get recreated every time it is being called, and therefor trying to managed my data in the controller did a mess since the Ajax call has its promise promise return async then it recreates the controller.
the solution to that is to manage ONLY BEHAVIORS in your controller and all data in a service/factory/provider.
so here is the new JS:
var VODCatalogModule = angular.module('VODCatalogModule', []);
VODCatalogModule.factory('VODCatalogFactory', function($http) {
var VODFactory = [];
VODFactory.VODCatalogLevel = 1;
VODFactory.PARENT_VOD_CATALOG_GK;
VODFactory.getVODCatalogData = function (PARENT_VOD_CATALOG_GK) {
var url = "VODCatalogHandler.ashx?action=GetVODCatalogData&vodLevel=" + VODFactory.VODCatalogLevel;
if (PARENT_VOD_CATALOG_GK)
url += "&PARENT_VOD_CATALOG_GK=" + PARENT_VOD_CATALOG_GK;
return $http.get(url, { cache: true });
};
VODFactory.changeVODCatalog = function (level, PARENT_VOD_CATALOG_GK){
VODFactory.VODCatalogLevel = level;
VODFactory.PARENT_VOD_CATALOG_GK = PARENT_VOD_CATALOG_GK;
};
return VODFactory;
});
var testWPDefinedView = 'TopLevelView';
//var testWPDefinedView = 'LowLevelView';
VODCatalogModule.config(function ($routeProvider) {
$routeProvider.when('/TopLevelView', { controller: 'VODCatalogController', templateUrl: '/_catalogs/masterpage/Yes/html/VODCatalog_TopLevelView.html' })
.when('/LowLevelView', { controller: 'VODCatalogController', templateUrl: '/_catalogs/masterpage/Yes/html/VODCatalog_LowLevelView.html' })
.otherwise({ redirectTo: '/' + testWPDefinedView });
});
function VODCatalogController($scope, $http, VODCatalogFactory) {
console.log("VODCatalogController ctor");
$scope.crumbsVisible = !$scope.BreadCrumbs || $scope.BreadCrumbs.length == 0 ? "hidden" : "";
$scope.catalogItemClick = function (catalogItem) {
VODCatalogFactory.changeVODCatalog(++VODCatalogFactory.VODCatalogLevel, catalogItem.VOD_CATALOG_GK);
};
VODCatalogFactory.getVODCatalogData().then(function(response){
$scope.BreadCrumbs = response.data;
$scope.MainCatalog = response.data;
$scope.NavCatalog = response.data;
});
VODCatalogModule.controller("VODCatalogController", VODCatalogController);
function VODCatalogController($scope, $http) {tofunction VODCatalog($scope, $http) {andVODCatalogModule.controller("VODCatalogController", VODCatalogController);toVODCatalogModule.controller("VODCatalogController", VODCatalog);