Copied to clipboard

Flag this post as spam?

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


  • David McDonnell 53 posts 251 karma points
    Jan 20, 2017 @ 15:01
    David McDonnell
    4

    Umbraco 7 Create a Custom Grid Editor

    Background: Recently I was trying to make a new Video Module in Umbraco that could be added to the grid as a standalone module rather than using the RTE.

    To do this I needed to create a custom plugin, I found the little documentation a little confusing as it was generally in the context of a custom property editor rather than a grid editor. Not being that familiar with Umbraco / Angular I have decided to document my findings for anyone in the future so they do not need to jump through the same hoops I did for something that should be relatively simple and quick.

    The Task:
    Create a custom grid editor that will load an embedded video onto the page and can be added to any column. This video will be embedded via an IFrame using any video provider that supports the embed option. e.g. Youtube / Vimeo

    Requirements:

    • The editor must be re-usable across the site
    • The user must be able to edit the video from the grid page in Umbraco via the overlay.
    • The Overlay must persist the current video URL
    • The Grid must show the video in Umbraco Grid view.
    • The result page must show the embedded video.

    Process:
    Step 1: Create a folder in the AppPlugins folder for the Plugin and name it accordingly

    Step 2: Create a new html file for the back office view and place in said new folder in App
    Plugins folder.
    Code Below:

    <div ng-controller="My.VideoModule.Controller">
    <div ng-if="control.value">
        <i class="icon icon-edit blue"></i>
        <a href="#" ng-click="openVideoDialog()" prevent-default="">
            Change Video
        </a>
    </div>
    <div ng-if="!control.value">
        <i class="icon icon-edit blue"></i>
        <a href="#" ng-click="openVideoDialog()" prevent-default="">
            Add Video
        </a>
    </div>
    
    <div ng-if="control.value.videoUrl">
    
    
    
    
    
    
    
    <iframe frameborder="0" src="{{control.value.videoUrl}}" width="100%" height="345"></iframe>
    
    
    
    
    
    
    
    </div>
    

    Here the src value ="{{control.value.videoUrl}}" is the value of the video input text box. In a grid editor you need to use "control .value" rather than the "model .value" used in property editors.

    Step 3: Create a js file in the same folder in the App_Plugins folder, this will be your controller.
    Code below:

        angular.module("umbraco").controller("My.VideoModule.Controller", function ($scope, dialogService) {
    
        $scope.openVideoDialog = function () {
            // open a custom dialog
    
            dialogService.open({
                // set the location of the view
                template: "../App_Plugins/VideoDialog/dialog.html",
                // pass in data used in dialog
                dialogData: $scope.control.value,
                // function called when dialog is closed
                callback: function (value) {
                    console.log("callback value url: " + value.videoUrl);
                    if (value != null && value !== '') {
                        //$scope.control.value = value.videoUrl;
                        $scope.control.value = {};
                        $scope.control.value.videoUrl = value.videoUrl;
                        /*
                        $scope.control.value.width = value.width;
                        $scope.control.value.height = value.height;
                        */
                    } 
                }
            });
        };
    });
    

    All this controller does is open a dialog window in umbraco, with a custom view specified by the template param:


    It specifies the data to pass to the dialog view : $scope.control.value
    This value contains all data that is set for the control i.e. if you have multiple fields.

    There is also a callback function specified which when the dialog is closed, the data from the dialog is fetched and passed back to the scope data of the control.

    $scope.control.value = {};
    $scope.control.value.videoUrl = value.videoUrl;
    

    We create a new model for the control and set a video Url param of that object model to the videoUrl of the dialog.

    Step 4: Create a package.manifest file in the same folder in App_Plugins this informs Umbraco that this new plugin exists and allows you to use it in the back office.

    {
          gridEditors:[
          {
            alias:"videoModule",
            name: "Video Module",
            view: "~/App_Plugins/VideoModule/VideoModule.Editor.html",
    
            icon: "icon-video"
          }
          ],
          javascript: [ "~/app_plugins/VideoModule/VideoModule.Controller.js" ]
    }
    

    This manifest file specifies the alias, name and view to be used by umbraco and also specifies the JS controller.

    Step 5: Create a cshtml view for your site to render a custom partial view for the video module, place this in the same plugin folder

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<dynamic>
    
    @if (Model.value != null)
    {
        <div class="video-col-container">
    
    
    
    
    
    
    
    <iframe frameborder="0" src="@Model.value.videoUrl"></iframe>
    
    
    
    
    
    
    
        </div>
    }
    

    Step 6: Create a Dialog Plugin to be used to configure the Video Url
    Again create a new folder in the App_Plugins folder for the dialog. e.g. "VideoDialog"

    Step 7: Create a new html view for the dialog and place in the videoDialog folder.

    <form name="dialogForm" ng-submit="submit(model)" ng-controller="My.VideoDialog.Controller">
        <umb-panel>
            <div class="umb-panel-body no-header umb-scrollable with-footer">
                <umb-pane>
                    <umb-control-group label="Video Url">
                        <input type="text" name="videoUrl" ng-model="model.videoUrl" ng-init="model.videoUrl" style="width: 100%" />
                    </umb-control-group>
                </umb-pane>
            </div>
            <div class="umb-panel-footer">
                <div class="btn-toolbar umb-btn-toolbar pull-right">
                    <a class="btn btn-link" ng-click="close()">
                        <localize key="cancel" />
                    </a>
                    <button type="submit" class="btn btn-primary" ng-disabled="!dialogForm.$valid">
                        <localize key="buttons_save">Save</localize>
                    </button>
                </div>
            </div>
        </umb-panel>
    
    </form>
    

    Here we have the form and inputs to submit to the grid editor, also the inputs should be populated if the values have already been set.
    The input text with name videoUrl specified and ng-model attribute and a ng-init attribute.

    ng-init can be used for setting the initial value if there is any and setting the ng-model value.

    ng-model keeps state and validation and registers with the parent form.
    Everything else is just a save and close button, which will trigger the callback method in the Grid Editor controller (Not the Dialog Controller).

    Step 8: Create a js controller for the Dialog and place in the dialog folder

    angular.module("umbraco").controller("My.VideoDialog.Controller", function ($scope) {
    
        if (typeof ($scope.dialogData.videoUrl) === 'object') {
    
            angular.element('input[name="videoUrl"]').value = '';
            /*
            angular.element('input[name="width"]').value = '';
            angular.element('input[name="height"]').value = '';
            angular.element('input[name="fullwidth"]').value = false;
            */
    
            $scope.model = {}
            $scope.model.videoUrl = '';
            /*
            $scope.model.width = '';
            $scope.model.height = '';
            $scope.model.fullwidth = false;
            */
        } else {
    
            $scope.model = {
                videoUrl: $scope.dialogData.videoUrl
                /*,
                width: $scope.dialogData.width,
                height: $scope.dialogData.height,
                fullwidth: $scope.dialogData.fullwidth
                */
            }
        }
    
    });
    

    Here we check if the current video URL is an object i.e. has no value. if so we set the value of the input equal to an empty string. This is to get around "[object] [object]" being set as the text on load if no value is present.

    Otherwise we just set the scope model video equal to the dialogData videoUrl.

    Scope Model in the dialog controller is the scope of the dialog view.

    Step 9: Create another package.manifest file for the dialog and place in the same dialog folder in the App_Plugins folder, this informs Umbraco of the dialog.
    Manifest File:

    {
        javascript: ["~/app_plugins/VideoDialog/dialog.js"]
    }
    

    Step 10: Go to the App_Data/TEMP/ClientDependancy folder and delete the contents, Umbraco can cache controls for the back office, if you do not see your new plugin this could be why, hitting the web.config can also help.

    Step 11: Go the the developer section in Umbraco and find the Grid DAta Type and edit the settings of the columns that you want to allow the video module to be used in.

    For this example click on 2 column and in the opening dialog select one of the columns, you will be provided with a list of grid editors, your new Video Module should be present here. Tick it and save.

    enter image description here

    Step 12: Go back to your page and grid tab and select the column and you should be allowed to add a video module. enter image description here enter image description here

    Video Dialog Opened on clicking link in column: enter image description here enter image description here I hope this helps anyone trying to create their first back office grid editor. It would have greatly helped me if I had it before.

    Cheers David

  • David Brendel 792 posts 2970 karma points MVP 3x c-trib
    Feb 03, 2017 @ 07:41
    David Brendel
    0

    Hi David,

    was there any special reason why you created the dialog in a seperate folder? Why not put it to the actual grideditor which uses the dialog?

    Regards David

  • David McDonnell 53 posts 251 karma points
    Feb 03, 2017 @ 13:38
    David McDonnell
    0

    Hi David, no reason at all, it was just a POC for a testing site, I wasn't really thinking of best practice for folder structure. Of course it is up to you as a developer to decide what your folder structure should be like.

    You could potentially re-use the dialog with multiple other video modules that you create, in that case it would make sense to separate it out to another folder

  • Dave Woestenborghs 3504 posts 12133 karma points MVP 8x admin c-trib
    Feb 04, 2017 @ 10:19
    Dave Woestenborghs
    0

    Hi David,

    Why did you create this ? Isn't this possible with Embed grid editor that ships with Umbraco ?

    Dave

  • David McDonnell 53 posts 251 karma points
    Feb 04, 2017 @ 10:27
    David McDonnell
    2

    It was meant as an informative post for anyone trying to create any type of grid editor not specifically for a video editor. Although with the embed grid editor you give control of the markup to the content editor, which usually is not the brightest of ideas when rolling out to non technical content editors.

    This way you control the markup and make sure that your brand styling is consistent

  • Dave Woestenborghs 3504 posts 12133 karma points MVP 8x admin c-trib
    Feb 04, 2017 @ 10:47
    Dave Woestenborghs
    0

    How can you give control of the markup to the editor with default embed editor ? Maybe I overlooked that option ?

    Dave

  • David McDonnell 53 posts 251 karma points
    Feb 04, 2017 @ 14:47
    David McDonnell
    0

    Hi Dave sorry I though you were taking about the embed HTML option in the Rich text editor. Anyway this post wasn't meant to be about creatin a video editor specifically, it was meant as a guide for creating any grid editor for the first time. I just used a video as an easy example.

  • David McDonnell 53 posts 251 karma points
    Apr 12, 2017 @ 11:37
    David McDonnell
    103

    Solution

Please Sign in or register to post replies

Write your reply to:

Draft