Custom section not showing views inside dashboard area

Hi there!

I’ve been trying for some time now to get my custom plugin working, but I’m stuck. It seems like none of my Angular controllers from init/resources.controller.js are being triggered when I try to navigate to list/create/edit views in my custom section.

Here’s my folder structure:

/App_Plugins/
└── Resources/
    ├── package.manifest
    ├── init/
    │   ├── routes.js
    │   └── resources.controller.js
    └── views/
        ├── resource-shell.html
        ├── resource-list.html
        ├── resource-create.html
        └── resource-edit.html

package.manifest

{
  "sections": [
    {
      "alias": "resources",
      "name": "Resources",
      "icon": "icon-documents",
      "showOnTablet": true
    }
  ],
  "dashboards": [
    {
      "alias": "resourceDashboard",
      "view": "/App_Plugins/Resources/views/resource-shell.html",
      "sections": [ "resources" ],
      "weight": 0
    }
  ],
  "trees": [
    {
      "alias": "resourcesTree",
      "section": "resources",
      "treeAlias": "resourcesTree",
      "name": "Resources"
    }
  ],
  "javascript": [
    "~/App_Plugins/Resources/init/routes.js",
    "~/App_Plugins/Resources/init/resources.controller.js"
  ],
  "css": []
}

In resource-shell.html, I’ve added an <ng-view> element to handle routing between views.

routes.js

angular.module("umbraco").config(function ($routeProvider) {

    $routeProvider
        .when("/resources/create", {
            templateUrl: "/App_Plugins/Resources/views/resource-create.html",
            controller: "Resources.CreateController"
        })
        .when("/resources/edit/:udi", {
            templateUrl: "/App_Plugins/Resources/views/resource-edit.html",
            controller: "Resources.EditController"
        })
        .when("/resources", {
            templateUrl: "/App_Plugins/Resources/views/resource-list.html",
            controller: "Resources.ListController"
        })
        .otherwise({
            redirectTo: "/resources"
        });

    console.log("🧠 routes.js loaded");
});

My controllers are not being hit
resources.controller.js

angular.module("umbraco").controller("Resources.ListController", function ($scope, $http, navigationService) {
    console.log("💥 ListController loaded", $routeParams); <--- This never get call'd
    $scope.children = [];

    $http.get("/umbraco/backoffice/Resources/ResourcesApi/Children")
        .then(res => $scope.children = res.data);
});

angular.module("umbraco").controller("Resources.CreateController", function ($scope, $http, $routeParams, notificationsService, navigationService) {

    console.log("💥 Resources.CreateController loaded"); <-- This never get call'd
    $scope.parentUdi = $routeParams.parentUdi || null;

    $scope.model = {
        title: "",
        type: "textResource",
        dataJson: "{}",
        parentUdi: $scope.parentUdi
    };

    $scope.save = function () {
        $http.post("/umbraco/backoffice/Resources/ResourcesApi/Create", $scope.model)
            .then(function (res) {
                notificationsService.success("Resource is added", "Your resource is saved");

                // Sync tree for at vise ny ressource
                navigationService.syncTree({
                    tree: "resourcesTree",
                    path: ["-1"], 
                    forceReload: true
                });

            })
            .catch(function (err) {
                console.error("❌ Create failed", err);
                notificationsService.error("error at creation", "insue the fields are correct and try again");
            });
    };
});

angular.module("umbraco").controller("Resources.EditController", function ($scope, $http, $routeParams, notificationsService, navigationService) {

    console.log("🛠 EditController loaded for UDI:", $routeParams.udi); <-- This is never get call'd
    $scope.udi = $routeParams.udi;
    $scope.model = null;
    $scope.loading = true;

    // Hent eksisterende ressource
    $http.get("/umbraco/backoffice/Resources/ResourcesApi/GetByUdi?udi=" + encodeURIComponent($scope.udi))
        .then(function (res) {
            $scope.model = res.data;
            $scope.loading = false;
        })
        .catch(function (err) {
            notificationsService.error("could get resource", "error reading data");
            $scope.loading = false;
        });

    // Gem ændringer
    $scope.save = function () {
        $http.post("/umbraco/backoffice/Resources/ResourcesApi/Update", $scope.model)
            .then(function () {
                notificationsService.success("Saved", "Resource er updated");
                navigationService.syncTree({ tree: "resourcesTree", path: ["-1"], forceReload: true });
            })
            .catch(function () {
                notificationsService.error("Fejl", "Changes could not be saved");
            });
    };
});

console.log("✅ controller.js is loaded!");

:thinking: What am I missing?

I suspect it’s something simple in how I’m registering the controllers or routes. Both routes.js and resources.controller.js exist and seem correct.

Copilot and I are just going in circles at this point :sweat_smile: — any help or fresh eyes would be much appreciated!

Thanks in advance :folded_hands:

Hey! Reading through the manifest it looks like you’re not loading the JavaScript files in.

Try adding the JavaScript array as below. I don’t know about functionality but you should hopefully see your console logs at least.

I’m on my phone, so watch out for dodgy iOS quotes!

{
    “dashboards”: { … same as above … },
    “javascript”: [ 
        “~/App_Plugins/Resources/init/routes.js",
        “~/App_Plugins/Resources/init/resources.controller.js"
  ]
}
1 Like

Hi Richard,

Thanks so much for helping :slightly_smiling_face:
I can see now that I had missed that part of the package.manifest.

I’ve added both routes.js and resources.controller.js to the javascript section, and included console.log statements to verify they are loaded — and they are! Both files log as expected in the browser console.

However, the routed views still don’t appear, and the controllers aren’t triggered when navigating. Any ideas what I might still be missing?

Thanks again!

Awesome - glad that’s taking a step in the right direction!

I’ve not tried to add in my own routes before, but I wonder if the core routes are conflicting with what you’re trying to do (matching on /:section? before it gets to your routes). You can see the Umbraco routes defined in the source.

Sounds like you might be trying to make a new CRUD section for custom items? If so, there’s an article from Paul Seal that might get you on the right track. It says 8 but the back office works roughly the same as in 13 - How to create a custom section and dashboard in Umbraco 8 | codeshare

EDIT: It’s worth noting that in Paul’s example he has loaded in the back office section/dash in code. The way you’re defining in the package.manifest is just an alternative way to do it :slight_smile:

Apologies for the long message.

I’m quite unsure whether I’m heading in the right direction here, or if there’s already a third-party package out there that solves the same problem I’m trying to address.

My goal is to remove static content – such as system links to published pages, simple lists used in tools like “Contentment,” etc. – from the main content area. I often find that things get cluttered, especially when these kinds of items are placed directly under the root node or in a child node pretending to be a “site settings” page.

As a solution, I’ve created a new root node with the doctype ResourcesRoot, under which I can recursively add custom resource doctypes. This entire “Resources” area sits nicely outside the regular content section – though ideally, it would belong under Settings or even in its own custom section.

My intention is to leverage Umbraco’s document types and data types to structure this resource area. However, I’m running into limitations with the IPublishedContent concept, since everything still has to be either published or unpublished. I’m looking for a way to break out of that model, without losing the benefits of Umbraco’s data structure and editor experience.

Eventually, I want to integrate this into my own system, UmbRes (Umbraco Resources), where I could fetch content like this:

UmbRes.T<BlockGridModel>("Layout.Footer", [lang=current])
UmbRes.T<IPublishedContent>("System.Nodes.NewsPage")

– and similar calls.

Umbraco’s Dictionary (Translate) already has a nice structure, but unfortunately, it’s limited to plain text only. If it could be extended to support complex objects or components, that would be ideal.

“I have a feeling I might have bitten off more than I can chew with this challenge.”

Does this make sense?

I see what you are trying to do, that’s definitely a fair amount of work just to declutter - but I can sympathise with wanting to do this!

If this is something you want to do, I’d suggest reading up on creating Sections and Trees. This should get you up and running with the routes to list/view. Once you have the core of it working I would advise checking out the Umbraco source.

Something you may find a nice happy medium is to hide that particular node from the tree unless you’re a specific user or user group. You can do that using notifications; specifically the TreeNodesRendering. Here’s how to use them.

:warning: Please bear in mind that v13 is EOL in not long over a year (Nov 2026) and v14+ uses a totally different backoffice so any custom work you’re doing in Angular will need to be rewritten to work with the latest version.

Hi Richard

Thanks for the info! I’ve decided to jump straight into version 16—let’s see how that goes :grinning_face_with_smiling_eyes:
Already hit the next challenge: resizing images in the TipTap editor. That one’s going to be interesting to crack!

Thanks again for your help.
Best regards,
Allan

1 Like