Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • J 445 posts 862 karma points
    Apr 29, 2021 @ 12:42
    J
    0

    Getting Angualr section to work with C# class

    Hi

    I am creating a custom section in Umbraco 7 and have a Class Library based on this article for the Controller

    https://our.umbraco.com/Documentation/Tutorials/Creating-a-Property-Editor/part-4-v7

    I have 2 Class Libraries. Class Library One adds a section and other class builds on the link above.

    I add a reference to the class library two within the Umbraco 7 project. I can already see my custom section and then manually generate files under the app_plugins directory.

    I can see the edit.html page. As soon as i add

    <div ng-controller="My.FacilityController ">
    

    I get the error "Error: Argument 'My.FacilityController ' is not a function, got undefined"

    I have a package.manifest file and a resource.js, controller.js registered in here.

    {
    javascript: [
    "~/App_Plugins/CustomSection/backoffice/CustomSectionTree/facility.Resource.js",
    "~/App_Plugins/CustomSection/backoffice/CustomSectionTree/Facility.Controller.js",
    ],
    css: [
    "~/App_Plugins/CustomSection/backoffice/CustomSectionTree/companystyle.css"
    ]
    }
    

    Im not sure where the problem is, is it within one of the js files or if i simply have the wrong combination/name of my controller set.

    My class (i will leave class library one out as that only adds a section)

    namespace CompanyName
    {
        [Umbraco.Web.Mvc.PluginController("My")]
        public class FacilityController : UmbracoAuthorizedApiController
        {
            [HttpGet]
            public string GetName()
            {
                return "Bob";
            }
        }
    }
    

    Ive tried a combination of names for the ng-controller but each time its the same error with the different name ive used in the edit.html file.

    Any thoughts what i could be doing wrong somewhere?

    Thanks

  • Adam Hearn 13 posts 109 karma points
    Apr 29, 2021 @ 14:57
    Adam Hearn
    0
    <div ng-controller="My.FacilityController">
    

    That markup that wires up a JavaScript controller using Angular. You need to be referring to the name of the controller as defined by file listed within the package manifest:

    "~/App_Plugins/CustomSection/backoffice/CustomSectionTree/Facility.Controller.js",
    

    Within that file you should have an angular statement such as (the controller name must [obviously] match):

       angular.module("umbraco").controller("My.FacilityController", ...
    

    From there the JavaScript controller will have functions that call the server (via $http). Hope that helps. Just take a look at the code for App_PlugIns that do similar things.

  • J 445 posts 862 karma points
    Apr 29, 2021 @ 15:06
    J
    0

    I thought the same but this is my controller.js file

    (function () {
        'use strict';
        angular.module("umbraco")
            .controller("My.FacilityController", function ($scope, facilityResource) {
                facilityResource.getName.then(function (response) {
                    $scope.getName = response.data;
                });
            });
    })();
    

    Does this look correct? Some threads suggest it maybe a compile time error but Visual Studio isnt raising any.

  • Adam Hearn 13 posts 109 karma points
    Apr 29, 2021 @ 15:21
    Adam Hearn
    0

    Looks OK; check that you haven't got a trailing space after the class name:

    <div ng-controller="My.FacilityController ">
    

    If you can post full files that are stripped back to the basics of a view with minimal markup, a controller with minimal functionality etc. it might be easier to diagnose.

  • J 445 posts 862 karma points
    Apr 29, 2021 @ 15:38
    J
    0

    I think that mightve been a typo but im certain there is no trailing space. This is the edit.html file

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
    <script>
    
    </script>
    
    <div ng-controller="My.FacilityController">
    
        <umb-panel>
            <umb-header tabs="content.tabs">
                <div class="umb-headline-editor-wrapper span12 ng-scope">
                    <h1 class="ng-binding">My custom section {{id}}</h1>
                </div>
            </umb-header>
    
            <umb-tab-view>
                <umb-tab id="tab1" rel="svensson">
    
                    <div class="umb-pane">
                        This is tab content for tab 1<br />
                        <p ng-show="EditMode()">
                            <span class="label label-warning">In create mode, this label is only showed when the controller sees the create-querystring item.</span>
                        </p>
                    </div>
                </umb-tab>
    
                <umb-tab id="tab2" rel="kalle">
    
                    <div class="umb-pane">
    
                        This is tab content for tab 2
                    </div>
                </umb-tab>
    
            </umb-tab-view>
        </umb-panel>
    
    </div>
    </body>
    </html>
    

    The project structure is

    C:\Dev\Client\Web\App_Plugins\CustomSection\backoffice\CustomSectionTree
    

    The package.manifest file reside under

    C:\Development\ClientOne\Web\App_Plugins\CustomSection\backoffice
    

    (So there is the folder CustomSectionTree too)

    Im not sure if there is a working example/project i could take to compare? Thanks for your help

  • Adam Hearn 13 posts 109 karma points
    Apr 29, 2021 @ 15:51
    Adam Hearn
    0

    The edit.html file is a fragment and thus should not have any of the page level markup (delete everything before <div ng-controller... and the closing body and html tags).

    Please post the complete js file too. I assume you had already posted the full manifest?

    I'm not sure how Umbraco locates manifest files but yours is one level deeper than I'd have expected. Maybe relocate it "C:\Development\ClientOne\Web\App_Plugins\CustomSection"?

    Also, when you run the page, what errors are coming out in the Browser Console?

  • J 445 posts 862 karma points
    Apr 29, 2021 @ 16:52
    J
    0

    The complete js file is above for the controller. Do you want to see the resource?

    I removed the HTML you mentioned so it just starting from

    <div ng-controller....
    

    I tried relocating the manifest file to one location above and still no luck (by the way the entire manifest file is in my first post).

    When i click the new section and click the single item in the browser i see

    angular.min.js?cdv=2:63

    Error: Argument 'My.FacilitatorController' is not a function, got undefined at cb (angular.min.js?cdv=2:17) at xa (angular.min.js?cdv=2:17) at angular.min.js?cdv=2:53 at angular.min.js?cdv=2:44 at n (angular.min.js?cdv=2:7) at k (angular.min.js?cdv=2:44) at e (angular.min.js?cdv=2:40) at angular.min.js?cdv=2:39 at angular.min.js?cdv=2:158 at angular.min.js?cdv=2:100

    Just a reminder that the class is in a dll of its own and doesnt sit in a class under the app_code folder. Not sure if its a namespace thing?

    Edit

    So i cleared my cache to see if that made a difference and now i receive the error

    angular.min.js?cdv=2:63 Error: Unknown provider: facilityResourceProvider <- facilityResource
    

    Looks to me its hitting that file but maybe something else is not entirely correct?

    Pressing F5 seems to bounce between the two errors :-(

  • Adam Hearn 13 posts 109 karma points
    Apr 30, 2021 @ 00:04
    Adam Hearn
    0

    Just a reminder that the class is in a dll of its own and doesnt sit in a class under the app_code folder. Not sure if its a namespace thing?

    I'm not sure I follow... the issue you're having is within the client code only; the server code (C#) is not relevant at this time...

    I'm reasonably sure it's a simple misunderstanding/typo or similar so I suggest going back to basics and reviewing what you have.

    Here's an example with folder App_Plugins\AcmeMembers containing 3 files

    package.manifest

    {
        javascript: [
            '~/App_Plugins/AcmeMembers/AdvancedMembersController.js'
        ]
    }
    

    AdvancedMembers.html

    <div class="umb-dialog umb-pane" ng-controller="Acme.AdvancedMembersController">
        <div class="umb-dialog-body">
    
            <umb-load-indicator ng-if="working"></umb-load-indicator>
    
            <p class="umb-abstract">
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sit amet pretium nulla. Aenean gravida nisl ut orci euismod tincidunt in sed nulla. Ut maximus urna eu facilisis blandit. Vivamus feugiat justo est, non fringilla neque sollicitudin pharetra. Cras varius ex vitae nisl viverra efficitur. Vestibulum laoreet est ut metus sollicitudin, sit amet placerat massa consectetur. Praesent nec dui massa. Proin nec consequat diam. Mauris porttitor ullamcorper justo, sit amet malesuada leo pretium a. Sed a congue ante, at fringilla dolor. Vestibulum suscipit augue est, in mattis nisl semper non.
            </p>
    
            <umb-confirm on-confirm="performAction" on-cancel="cancel" />
        </div>
    </div>
    

    AdvancedMembersController.js

    angular.module("umbraco").controller("Acme.AdvancedMembersController",
        function ($http, $scope, navigationService, notificationsService) {
            $scope.performAction = function () {
    
                $scope.working = true;
    
                // Send the request to the server
                $http({
                    method: 'POST',
                    url: '/umbraco/surface/AcmeMembers/Action',
                    data: '{something}'
                }).then(function successCallback(response) {
                    $scope.working = false;
                    navigationService.hideDialog();
                }, function errorCallback(response) {
                    $scope.working = false;
                    notificationsService.error("Error", "Could not perform action");
                });
            }
    
            $scope.cancel = function () {
                navigationService.hideDialog();
            };
        }
    );
    

    You'll need to wire up a tree menu via info in the docs

  • J 445 posts 862 karma points
    Apr 30, 2021 @ 13:16
    J
    0

    Thanks for that - i added your js and HTML by replacing the one from the tutorial and i can see the lorem ipsum along with a cancel/ok button - without any console errors. This is strange as i have nothing related with Acme.AdvancedMembersController - Is this custom to you?

    Now i need to re-visit that tutorial to see how the heck i get the data!!

    As for the Class Library - in the past i came across an issue where the class library which was in a separate project wasnt correctly being recognised. Only when i moved the class library into the App_Code folder did things start to work. That may have been due to a bug in Umbraco or something in previous versions but i wanted to mention in case that had any relevance. Just to clarify on this to make sure i haven't missed something, this is what the separate class library looks like, which im adding a reference into the web project

    namespace CompanyName{
    [Application("CustomSection", "CustomSection", "icon-settings", 15)]
        public class CustomSectionApplication : IApplication { }
        [PluginController("CustomSection")]
        [Umbraco.Web.Trees.Tree("CustomSection", "CustomSectionTree", "My custom section", iconClosed: "icon-doc")]
        public class CustomSectionTreeController : TreeController
        {
            protected override MenuItemCollection GetMenuForNode(string id, System.Net.Http.Formatting.FormDataCollection queryStrings)
            {
                var menu = new MenuItemCollection();
                menu.DefaultMenuAlias = ActionNew.Instance.Alias;
                menu.Items.Add<ActionNew>("Create");
                return menu;
            }
    
            protected override TreeNodeCollection GetTreeNodes(string id, System.Net.Http.Formatting.FormDataCollection queryStrings)
            {
                var nodes = new TreeNodeCollection();
    
                if (id == "-1")
                {
                    var item = this.CreateTreeNode("dashboard", id, queryStrings, "My item", "icon-truck", true);
                    nodes.Add(item);
                }
    
                return nodes;
            }
        }}
    
Please Sign in or register to post replies

Write your reply to:

Draft