Is there any way, from my tree controller, to add a parameter to the routePath, without encoding the "?", so that I can use $routParams.tag in my angular controller?
Unfortunately, the query string collection modified here is the one sent to the server when asking for the childnodes of that node. It is not the client side angular route of the node.
Sorry for the duff reply. I did a little research and what i found seemed to suggest angular doesn't (or isn't in this case going to) support query strings.
If you fancy doing a bit of route hijacking for angular (and copying can route out of umbraco route.js which i don't like) then a test of this worked to pass the tag value into routeparams.
'use strict';
var app = angular.module("umbraco");
app.config(function ($routeProvider) {
var canRoute = function (isRequired) {
return {
/** Checks that the user is authenticated, then ensures that are requires assets are loaded */
isAuthenticatedAndReady: function ($q, userService, $route, assetsService, appState) {
var deferred = $q.defer();
//don't need to check if we've redirected to login and we've already checked auth
if (!$route.current.params.section
&& ($route.current.params.check === false || $route.current.params.check === "false")) {
deferred.resolve(true);
return deferred.promise;
}
userService.isAuthenticated()
.then(function () {
assetsService._loadInitAssets().then(function () {
//This could be the first time has loaded after the user has logged in, in this case
// we need to broadcast the authenticated event - this will be handled by the startup (init)
// handler to set/broadcast the ready state
var broadcast = appState.getGlobalState("isReady") !== true;
userService.getCurrentUser({ broadcastEvent: broadcast }).then(function (user) {
//is auth, check if we allow or reject
if (isRequired) {
// U4-5430, Benjamin Howarth
// We need to change the current route params if the user only has access to a single section
// To do this we need to grab the current user's allowed sections, then reject the promise with the correct path.
if (user.allowedSections.indexOf($route.current.params.section) > -1) {
//this will resolve successfully so the route will continue
deferred.resolve(true);
} else {
deferred.reject({ path: "/" + user.allowedSections[0] });
}
}
else {
deferred.reject({ path: "/" });
}
});
});
}, function () {
//not auth, check if we allow or reject
if (isRequired) {
//the check=false is checked above so that we don't have to make another http call to check
//if they are logged in since we already know they are not.
deferred.reject({ path: "/login/false" });
}
else {
//this will resolve successfully so the route will continue
deferred.resolve(true);
}
});
return deferred.promise;
}
};
};
$routeProvider.when('/mypackagesection/:tree/:method/:id/tag/:tag', {
//This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
template: "<div ng-include='templateUrl'></div>",
//This controller will execute for this route, then we replace the template dynamnically based on the current tree.
controller: function ($scope, $route, $routeParams, treeService) {
if (!$routeParams.tree || !$routeParams.method) {
$scope.templateUrl = "views/common/dashboard.html";
}
// Here we need to figure out if this route is for a package tree and if so then we need
// to change it's convention view path to:
// /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html
// otherwise if it is a core tree we use the core paths:
// views/{treetype}/{method}.html
var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree);
if (packageTreeFolder) {
$scope.templateUrl = Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath +
"/" + packageTreeFolder +
"/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html";
}
else {
$scope.templateUrl = 'views/' + $routeParams.tree + '/' + $routeParams.method + '.html';
}
},
resolve: canRoute(true)
})
})
app.controller(
"MyPackage.EditItemController",
function ($scope, $routeParams)
}
);
I've "solved" it for now by simply adding a redirecting controller:
angular.module("umbraco").controller("Foo.FoorByTagController",
function($scope, $routeParams, $location, notificationsService, navigationService) {
// This controller is basically just a way to generate the correct search url, and redirect to it.
$location.search("tag", $routeParams.id);
$location.path("/" + $routeParams.section + "/" + $routeParams.tree + "/" + "search" + "/" + "-1");
$location.replace();
});
Angular does support this, so it looks more like the Umbraco API was not built for allowing to add them to routePaths from the server.
Thanks for the example. but I think route hijacking seems a bit much just for this relatively simple task.
I saw location.search but thought you needed a query string for it to work, didnt know you could search within a route parameter. Glad you found your workaround
Looking at the source for the navigation.controller.js-file we can see that Umbraco Core only calls $location.Path which will encode any query-parameters.
By adding an item to the node.AdditionalData-dictionary we can have our own js-code executing on click. The nice thing is that the code is executed using js-eval() and thanks to closures we have access to all the variables in the scope.
So in the TreeController-code (C#) when creating a TreeNode we can add this javascript function to set the search-parameters on the $location-service, like this:
var dictionaryParameters = new Dictionary<string,string>();
dictionaryParameters.Add("queryParam1","value");
var queryParamsJsObj = JsonConvert.SerializeObject(dictionaryParameters).Replace("\"", "'");
// Code in the js-function is copied from: https://github.com/umbraco/Umbraco-CMS/blob/55c37e0a4efacfce48c3d776b2893dd076625049/src/Umbraco.Web.UI.Client/src/navigation.controller.js#L93
var js = @"(function(){
//add action to the history service
historyService.add({ name: n.name, link: n.routePath, icon: n.icon });
//put this node into the tree state
appState.setTreeState('selectedNode', args.node);
//not legacy, lets just set the route value and clear the query string if there is one.
$location.path(n.routePath);
navigationService.clearSearch();
$location.search(" + queryParamsJsObj + @");
})()";
node.AdditionalData.Add("jsClickCallback",js);
Adding querystring to RoutPath on custom tree
I'm building a custom section with a custom tree.
The tree is sort of a filter of some underlying data. So my tree looks something like this:
MyTree
Now, when I click the "MyTree" root node, I go to a search page like this:
/umbraco#/mysection/mytree/search/-1
When I click the "Tag 3" node, I would like it to pass a parameter to that route, like this:
/umbraco#/mysection/mytree/search/-1?tag=3
But if I make me tree node like this:
Then the url I get is
/umbraco#/mysection/mytree/search/-1%3Ftag=3
Is there any way, from my tree controller, to add a parameter to the routePath, without encoding the "?", so that I can use $routParams.tag in my angular controller?
Hi,
would also be interested in a solution. Had the problem myself and in the end refactored my code as I didn't found a solution.
I don't know if this the 'correct' way and I was interested in modifying a key already present but you could try the same method I used recently.
Unfortunately, the query string collection modified here is the one sent to the server when asking for the childnodes of that node. It is not the client side angular route of the node.
Sorry for the duff reply. I did a little research and what i found seemed to suggest angular doesn't (or isn't in this case going to) support query strings.
If you fancy doing a bit of route hijacking for angular (and copying can route out of umbraco route.js which i don't like) then a test of this worked to pass the tag value into routeparams.
I've "solved" it for now by simply adding a redirecting controller:
Angular does support this, so it looks more like the Umbraco API was not built for allowing to add them to routePaths from the server.
Thanks for the example. but I think route hijacking seems a bit much just for this relatively simple task.
I saw location.search but thought you needed a query string for it to work, didnt know you could search within a route parameter. Glad you found your workaround
Hi guys!
I had the same issue, wanting to add a querystring to the route for TreeNode.
In AngularJS one need to pass any qyerystring to the $location-service by calling the search()-method,
Looking at the source for the navigation.controller.js-file we can see that Umbraco Core only calls $location.Path which will encode any query-parameters.
But... there is a way to pass custom javascript to be executed on click: https://github.com/umbraco/Umbraco-CMS/blob/55c37e0a4efacfce48c3d776b2893dd076625049/src/Umbraco.Web.UI.Client/src/navigation.controller.js#L71
By adding an item to the node.AdditionalData-dictionary we can have our own js-code executing on click. The nice thing is that the code is executed using js-eval() and thanks to closures we have access to all the variables in the scope.
So in the TreeController-code (C#) when creating a TreeNode we can add this javascript function to set the search-parameters on the $location-service, like this:
Hope this helps if anyone has the same issue =D
Cheers!
is working on a reply...