Copied to clipboard

Flag this post as spam?

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


  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Oct 29, 2014 @ 09:52
    Rasmus Fjord
    0

    Building custom grid editors

    Yo :) 

    Im doing a small demo presentation for a client, and they some special requests, so i wanted to try and build a small prototype. 

    So what i want to do is building a custom editor for the new grid. 

    I have added a new editor to the config/grid-editors... 

    I have added a new propertyeditor html file in the umbraco/view/... folder.

    So what i want is to add a dropdown above a RTE field, but im having a hard time to figure out how, anyone who got a pointer for me ?

  • Dave Woestenborghs 3504 posts 12134 karma points MVP 9x admin c-trib
    Oct 29, 2014 @ 10:14
    Dave Woestenborghs
    0

    Hi Rasmus,

    A good staring point is the Umbraco source.

    If you look at the umbraco source code you can find it in https://github.com/umbraco/Umbraco-CMS/tree/7.2.0/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors

    This will give you a good idea on how to create your own angular based editor

    You will also need to add your editor to the grid config found in : /config/grid.editors.config.js

    And next you need to create a MVC view for rendering your grid. Examples can be found in the folder /Views/Partials/Grid/Editors

    Dave

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Oct 29, 2014 @ 14:30
    Rasmus Fjord
    0

    Thanks Dave. 

    So far so good, think you got me one the right track and Ill try to take it from there.

  • Dave Woestenborghs 3504 posts 12134 karma points MVP 9x admin c-trib
    Oct 29, 2014 @ 14:35
    Dave Woestenborghs
    0

    You will be amazed by the power and the flexibility of the grid once you get the hang of it.

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Oct 29, 2014 @ 15:12
    Rasmus Fjord
    0

    I got it working ! :D 

    but found a "wall" that i dunno how to get over. 

    Inside my property editor(lets call it coloredbox) i have 2 property editors.

    A dropdown where you pick a color and a textbox.

    But the issue is that im using the "control.value" as a model, but they are being used on both properties inside one big property.

    So just to dump some code i have the following :

    <div ng-controller="My.ColorPickerController">
    
        <select ng-model="control.value" name="svufcolor">
            <option selected="selected" value="-1">Choose...</option>
            <option value="627991">Havblå(standard)</option>
            <option value="A9C2D9">Himmelblå</option>
            <option value="CCC9B0">Sand</option>
            <option value="8F5368">Lyng</option>
            <option value="8F9F84">Mørk Mos</option>
            <option value="C8CCB5">Lys Mos</option>
            <option value="3E424D">General Grå</option>
            <option value="bb0000">Julerød</option>
            <option value="df791e">Sunset</option>
            <option value="259FF4">SeaBlue</option>
        </select>
    
    </div>
    
    <div ng-controller="Umbraco.PropertyEditors.Grid.TextStringController">
        <textarea class="textstring input-block-level" id="{{control.uniqueId}}_text"
                  ng-keyup="adjustSize($event)" ng-model="control.value"
                  ng-attr-style="{{control.editor.config.style}}" placeholder="Write here..."></textarea>
    </div>
    
  • Dave Woestenborghs 3504 posts 12134 karma points MVP 9x admin c-trib
    Oct 29, 2014 @ 16:15
    Dave Woestenborghs
    0

    I don't see why you need 2 controllers to start with.

    You can extend the control.value property of your scope like you want.

    In your case you would have something linke

    control.value.svufcolour

    and control.value.text

     

    Dave

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Oct 30, 2014 @ 09:34
    Rasmus Fjord
    0

    Well since i dont know much on how the angular world works this was how i thought it should be done.

    So your saying that i can just extend it ! LOVELY :)

    Will try it, thx dave for learning an angular noob some tricks.

  • Dave Woestenborghs 3504 posts 12134 karma points MVP 9x admin c-trib
    Oct 30, 2014 @ 12:21
    Dave Woestenborghs
    0

    I still consider my self a angular noob. Only thing I used angular for is extending the Umbraco Backend. I love the power of this technology.

     

    Dave

  • yogesh pathak 136 posts 221 karma points
    Jun 01, 2015 @ 11:58
    yogesh pathak
    0

    Hey guys,

    can you please give an example of how to create renderer view for the above grid editor by Rasmus?

    Thanks in advance

    Yogesh

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 01, 2015 @ 12:06
    Rasmus Fjord
    0

    Yo Yogesh 

    What is it you wanna do, that might be easier to understand for me :) 

    And yea i can probably give you an example code.

  • yogesh pathak 136 posts 221 karma points
    Jun 01, 2015 @ 13:07
    yogesh pathak
    0

    Hi Rasmus,

    I need to create a grid editor by which i can set "Tab heading" and "Tab Content (text only)" , and this should be rendered like bellow screeshot

    is it clear what i want now?

    Yogesh

     

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 01, 2015 @ 13:11
    Rasmus Fjord
    0

    So what you want to build is a "tab" like widget to be used inside the grid ?

  • yogesh pathak 136 posts 221 karma points
    Jun 01, 2015 @ 13:17
    yogesh pathak
    0

    this is how i have created my grid editor

    and i want  whatever i will insert into this heading and text field it should be renderd like a tabed content (i have attached screenshot of that in my last comment)

    is it clear now?

    Yogesh

  • Urvish 252 posts 776 karma points
    Jun 01, 2015 @ 13:25
    Urvish
    0

    Hi Yogesh,

    You can do one thing.

    Take grid with Heading and Content only.

    Then make news rows as per the tabs. Means 1 tab = 1 row.

    Then you can set html from the view by getting row of grid.

    This will be easy for you to achieve this kind of functionality.

    Hope this will help you.

    Regards,

    Urvish Mandaliya

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 01, 2015 @ 13:27
    Rasmus Fjord
    1

    Arh okay yeah i think i get it now, either way i would do like this:

    My example is on how to create a custom "youtube" item. 

    First of all i would start by going into /config/grid.editors.config.js and add the following :

    ,
        {
            "name": "Youtube",
            "alias": "youtube",
            "view": "/app_plugins/CodeMonkey.Youtube/youtube.html",
            "icon": "icon-movie-alt"
        }

    The above lines does that you can pick the "youtube" when selecting a grid widget.

    The folder that "view" references, would be where i have my view and controller for the grid item aswell.

    inside my "/CodeMonkey.Youtube" folder i have 4 files :

    Package.manifest (manifest file)
    youtube.cshtml (view used to render for the user)
    youtube.html (view used to render in the grid in the backend)
    youtubeController.js (the controller that handles saving and loading the data.)

    Package.manifest 

    {
        javascript:[
            "/app_plugins/CodeMonkey.Youtube/youtubeController.js"
        ]
    }

    youtube.html

    <div ng-controller="CodeMonkey.YoutubeController" class="umb-editor umb-contentpicker">
        <div class="usky-editor-placeholder" style="text-align:left;">
            <img src="http://img.youtube.com/vi/{{control.config.splittedLink}}/0.jpg" ng-if="control.config.splittedLink" style="z-index: 10;position: relative; width: 100%; max-width: 300px;" />
            <br ng-if="control.config.splittedLink" />
            <div ng-show="control.config.showControls">
                <input type="text" ng-model="control.config.link" ng-change="changeContents()" placeholder=" youtube link" />
                <div class="help-text" style="z-index:10;position:relative; font-size:12px; margin:5px 0;">Eks. "https://www.youtube.com/watch?v=5VWGw5itaug" </div><br />
                <input type="text" ng-model="control.config.height" placeholder="Højde" />
                <div class="help-text" style="z-index:10;position:relative; font-size:12px; margin:5px 0;">
                    Eks. "400px", hvis ingen højde er sat vil der blive brugt en standard
                </div>
                <label><input type="checkbox" ng-model="control.config.toolbar" />&nbsp; Fjern youtubes toolbar? </label>
            </div>
    
            <a class=""  style="display:inline-block;margin-top: 5px;padding: 4px 8px;background: #f2f2f2;border: 1px solid #ccc;" ng-if="control.config.link" ng-click="showConfig()">
                <i style="margin:0;display: inline-block;font-size: 14px;line-height:normal; color: #000;padding-right: 5px;" class="icon icon-edit"></i>Ret
            </a>
            <i class="icon icon-movie-alt" style="position: absolute;right: 20px;top: 40px;font-size: 10em;color:#E8E8E8;"></i>
        </div>
    
    </div>
    
    youtubeController.cshtml
    angular.module("umbraco").controller("CodeMonkey.YoutubeController", function ($scope) {
        if ("config" in $scope.control) {
            $scope.control.config.showControls = false;
        }
        else {
            $scope.control.config = { showControls:true};
        }
    
        $scope.changeContents = function () {
            var splitted = $scope.control.config.link.split('v=')[1];
            if (splitted.indexOf("&") > -1) {
                $scope.control.config.splittedLink = splitted.split('&')[0];
            }
            else {
                $scope.control.config.splittedLink = splitted;
            }
    
        };
        $scope.showConfig = function () {
            if ($scope.control.config.showControls == true) {
                $scope.control.config.showControls = false;
            }
            else {
                $scope.control.config.showControls = true;
            }
    
        };
    });
    
    Youtube.cshtml
    @inherits Umbraco.Web.Mvc.UmbracoViewPage<dynamic>
    @{
    
        string youtubeid = Model.config.splittedLink;
        string height = "";
        string toolbar = "1";
        if (Model.config.height != null)
        {
            height = string.IsNullOrEmpty(Model.config.height.ToString()) == true ? "400px" : Model.config.height.ToString();
        }
        else
        {
             height = "400px";
        }
        if (Model.config.toolbar != null)
        {
            toolbar = Model.config.toolbar == true ? "0" : "1";
        } 
    }
    <iframe width="100%" height="@height" class="youtube" src="//www.youtube.com/embed/@youtubeid?controls=@toolbar&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>
    

    That is a full example on how to build a small grid widget.

  • yogesh pathak 136 posts 221 karma points
    Jun 01, 2015 @ 14:16
    yogesh pathak
    0

    hi,

    @Urvish-Yes this is exctly what i am planning :)

    @Rushmus-Thanks this is what i was looking for (a complete example)

    Thanks

    yogesh

  • Urvish 252 posts 776 karma points
    Jun 01, 2015 @ 14:21
    Urvish
    0

    Yogesh,

    After successful implementation , you could put your code here.

    So that others can get idea about such kind of functionality. :)

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 01, 2015 @ 14:22
    Rasmus Fjord
    0

    Awesome Yogesh :)

    The example above is in production and runs great, shout if something dosnt work for you. 

    The good part with that example is that im saving multiple values and such.

  • yogesh pathak 136 posts 221 karma points
    Jun 01, 2015 @ 14:26
    yogesh pathak
    0

    @Urvish - For sure :)

    @Rasmus - Exctly, i was looking for same example it made my way smoother :)

  • yogesh pathak 136 posts 221 karma points
    Jun 02, 2015 @ 11:10
    yogesh pathak
    0

    Hey guys,

    Need some help , i am able to create multiple rows in this grid editor but not able to save data for , i mean when i click on save and publish data seems to be lost and table with one blank rows is being shown

    bellow is my code

    html

    <div ng-controller="Grid.ParagraphGroupController">
        <table class="table">
            <tr>
                <th>Heading</th>
                <th>Text</th>
            </tr>
            <tr ng-repeat="tabData in tabelsData">
                <td>
                    <input ng-show="true" ng-model="tabData.header" type="text" />
                </td>
                <td>
                    <textarea ng-show="true" ng-model="tabData.content"> </textarea>
                </td>
            </tr>
            <tr class="lastRow">
                <td> <button class="btn btn-default" type="button" ng-click="AddRow()">+</button></td>
                <td></td>
                </tr>
        </table>
    </div>
     
    js controller
     
    angular.module("umbraco").controller("Grid.ParagraphGroupController", function ($scope) {
        $scope.id = 1;

        $scope.tabelsData = [
        { 'heading': '', 'content': '', 'id': $scope.id }
        ];

        $scope.AddRow = function () {
            $scope.id++;
            $scope.tabelsData.push({ 'heading': '', 'content': '', id: $scope.id });
           
        };
    });
     
    any thing what i am doing wrong here?
     
    regards
    Yogesh

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 02, 2015 @ 11:24
    Rasmus Fjord
    0

    Remember in your view that you input for the heading is called: tabData.heading not tabData.header.

    but in your function to add the data to your json your not saving any data 

       $scope.tabelsData.push({ 'heading': 'some data here', 'content': ' and here', id: $scope.id });

    Also on load your overwriting the data :

     $scope.tabelsData = [

        { 'heading': '', 'content': '', 'id': $scope.id }

        ];

  • yogesh pathak 136 posts 221 karma points
    Jun 02, 2015 @ 11:32
    yogesh pathak
    0

    ok my bad , one more question how can i setup a condition on load by which data can be prevented from overwrite?

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 02, 2015 @ 11:36
    Rasmus Fjord
    0

    No biggy man ! 

    Ive not tested it but i would use the "in" operator :

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in

    Try something like this :

    if (!("tabelsData" in $scope)) {
           $scope.tabelsData = [
        { 'heading': '', 'content': '', 'id': $scope.id }
           ];
        }
       
  • yogesh pathak 136 posts 221 karma points
    Jun 02, 2015 @ 11:53
    yogesh pathak
    0

    Hey Rusmus,

    here is my js

    angular.module("umbraco").controller("Grid.ParagraphGroupController", function ($scope) {
        if ("tabelsData" in $scope) {
            console.log("tabelsData Exist");
            var tableOldData = $scope.tabData;
            $scope.tabelsData = tableOldData;
        }
        else {
            console.log("tabelsData doesnt Exist");
            $scope.id = 1;
            $scope.tabelsData = [
            { 'heading': '', 'content': '', 'id': $scope.id }
            ];
        }

        $scope.ChangeContent = function ()
        {
            $scope.tabData = $scope.tabelsData;
            console.log("savedData", $scope.tabData);
        };

        $scope.AddRow = function () {
            $scope.id++;
            $scope.tabelsData.push({ 'heading': '', 'content': '', id: $scope.id });
           
        };
    });

     

    and here is the HTML

     

    <div ng-controller="Grid.ParagraphGroupController">
        <table class="table">
            <tr>
                <th>Heading</th>
                <th>Text</th>
            </tr>
            <tr ng-repeat="rowData in tabelsData">
                <td>
                    <input ng-show="true" ng-model="rowData.heading" type="text" />
                </td>
                <td>
                    <textarea ng-show="true" ng-model="rowData.content"></textarea>
                </td>
            </tr>
            <tr class="lastRow">
                <td> <button class="btn btn-default" type="button" ng-click="AddRow()">+</button></td>
                <td><button class="btn btn-default" type="button" ng-click="ChangeContent()">Check</button></td>
                </tr>
        </table>
    </div>

     

    its still not working , is anything left which i should  give a try?

    Thanks

    Yogesh

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 02, 2015 @ 11:58
    Rasmus Fjord
    0

    yeah :)

    What comes out when you save in the console, and when you load ? 

    Also your still not adding anything in your data, heading and content are still empty. But you should atleast get the right amount of rows saved. 

  • yogesh pathak 136 posts 221 karma points
    Jun 02, 2015 @ 12:07
    yogesh pathak
    0

    When i save (ChangeContent  method) it shows and object of array with the values i filled from Table rows,

    and when i load it says tabelsData doesnt Exist"

    what you mean by "Also your still not adding anything in your data, heading and content are still empty" i am pushing empty string into content and Header because i want these values be filled from UI (textBoxes)

     

     

     

     

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 02, 2015 @ 12:12
    Rasmus Fjord
    0

    Think i got it now 

    In your first line your asking something like :

    if ("tabelsData" in $scope) {

    But isnt it tabData we should look for ?

  • yogesh pathak 136 posts 221 karma points
    Jun 02, 2015 @ 12:17
    yogesh pathak
    0

    i tried with tabData too but it is still same :(

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 02, 2015 @ 13:17
    Rasmus Fjord
    0

    I got one thing you can try, i normally add data not directly $scope i always add it to $scope.control.something so i do like this :

    I do it because the other wouldnt work to good for me either

    if ("tabData" in $scope.control) {
            $scope.tabelsData =  $scope.control.tabData;
        }
        else {
              $scope.tabelsData = [
            { 'heading': '', 'content': '', 'id': $scope.id }
            ];
        }

    $scope.ChangeContent = function () { $scope.control.tabData = $scope.tabelsData; console.log("savedData", $scope.tabData); }; 
  • yogesh pathak 136 posts 221 karma points
    Jun 02, 2015 @ 14:45
    yogesh pathak
    0

    Hey Rasmus,

    That worked :)

    dont know why .

    one more question how can i access values of "tabData " in my renderer view?

    Thanks

    Yogesh

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 02, 2015 @ 14:53
    Rasmus Fjord
    0

    yeah you sure can just do it like this :

         <tr ng-repeat="rowData in control.tabData">

     

    Good to know it worked :) remember to mark as answer so others can use it :)

  • yogesh pathak 136 posts 221 karma points
    Jun 03, 2015 @ 07:05
    yogesh pathak
    0

    Hey Rasmus,

    i can not mark it as an answer because this thread is not started by me , but yes i have voted up your answer which can help others to tackle situation like this :) . and i will post my complete code here once completed for other people

    thanks

    Yogesh

  • yogesh pathak 136 posts 221 karma points
    Jun 03, 2015 @ 08:25
    yogesh pathak
    0

    Here is the working code

    HTMl

    <div ng-controller="Grid.myController">
        <table class="table">
            <tr>
                <th>Heading</th>
                <th>Text</th>
            </tr>
            <tr ng-repeat="rowData in control.tabelsData">
                <td>
                    <input ng-show="true" ng-change="ChangeContent()" ng-model="rowData.heading" type="text" />
                </td>
                <td>
                    <textarea ng-show="true" ng-change="ChangeContent()" ng-model="rowData.content"></textarea>
                </td>
                <td>
                    <button class="btn btn-default-red" type="button" ng-click="RemoveRow(rowData.id)">-</button>
                    </td>
            </tr>
            <tr class="lastRow">
                <td> <button class="btn btn-default" type="button" ng-click="AddRow()">+</button></td>
                </tr>
        </table>
    </div>

     

    Js controller

     

    angular.module("umbraco").controller("Grid.myController", function ($scope) {
        if (("tabData" in $scope.control)) {
            var tableOldData = $scope.control.tabData;
            $scope.control.tabelsData = tableOldData;
        }
        else {
            $scope.control.id = 1;
            $scope.control.tabelsData = [
            { 'heading': '', 'content': '', 'id': $scope.control.id }
            ];
        }
        $scope.ChangeContent = function ()
        {
            var tabelData = $scope.control.tabelsData;
            $scope.control.tabData = tabelData;
            console.log("tableData", $scope.control.tabelsData);
        };

        $scope.AddRow = function () {
            $scope.control.id++;
            $scope.control.tabelsData.push({ 'heading': '', 'content': '', id: $scope.control.id });
        };

        $scope.RemoveRow = function (id) {
            var index = -1;
            var comArr = eval($scope.control.tabelsData);
            for (var i = 0; i < comArr.length; i++) {
                if (comArr[i].id === id) {
                    index = i;
                    break;
                }
            }
            if (index === -1) {
                alert("Something gone wrong");
            }
            $scope.control.tabelsData.splice(index, 1);
            $scope.ChangeContent();
        };

    });

    and finally  renderer

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<dynamic>
    @{
        var hv = Model;
        var tabData = hv["tabData"];
        bool fisrttab = true;
    }
    <div class="bs-docs-example">
        <ul id="myTab" class="nav nav-tabs">
           @foreach (var row in tabData)
           {
              
               if (fisrttab)
               {
                <li class="active"><a href="#@row.id" data-toggle="tab">@row.heading</a></li>
                   fisrttab = false;
               }
               else
               {
                <li><a href="#@row.id" data-toggle="tab">@row.heading</a></li>
               }
           }
            @{
                fisrttab = true;
            }
        </ul>
        <div id="myTabContent" class="tab-content">
    @foreach (var row in tabData)
    {
        if (fisrttab)
        {
            <div class="tab-pane fade in active" id="@row.id">
                <p>@row.content</p>
            </div>
            fisrttab = false;
        }
        else
        {
            <div class="tab-pane fade" id="@row.id">
                <p>@row.content</p>
            </div>
        }
    }
        </div>
    </div>

     

    Cheers! :)

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 03, 2015 @ 08:28
    Rasmus Fjord
    0

    That is just awesome :) 

  • yogesh pathak 136 posts 221 karma points
    Jun 03, 2015 @ 09:09
    yogesh pathak
    0

    Hey Rasmus,

    Now i am creating a new grid editor with a slighter change in functionality - now i want to upload Image in place of content in this grid editor but is doesnt seems to be work , i have created a new thread regarding it you can follow it up here https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/65278-Creating-grid-editor-with-Image-upload-

    Thanks

  • Rasmus Fjord 675 posts 1566 karma points c-trib
    Jun 03, 2015 @ 09:21
    Rasmus Fjord
    0

    i followed it up already ;)

Please Sign in or register to post replies

Write your reply to:

Draft