Copied to clipboard

Flag this post as spam?

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


  • Marc Ferrold 24 posts 105 karma points
    Apr 22, 2015 @ 13:56
    Marc Ferrold
    4

    The Spirit of Sharing - Images With Links in a Grid

    Hello, good day, hi!

    I've fairly recently started working with Umbraco, and I've really been liking the grid so far. I've been experimenting a little with making custom property editors for use in it, and a co-worker requested the ability to set up an image with a link, without it being in an RTE.

    This seemed simple, yet also useful enough that I figured I'd share what I'd come up with. If anyone can use it, they're free to copy/paste it :) My own experience with this sort of stuff has been that examples felt either too complex or too specific, so I hope this helps someone else.

    There might be a better way of doing this particular thing (in which case I suspect it'll pop up here, so problem solved either way), but this is simple and hopefully easy to understand.

    In /App_Plugins/LinkImage (or whatever you choose to name your plugin):

    The controller (LinkImage.controller.js)

    angular.module("umbraco").controller("LinkImage.controller",
    function ($scope, dialogService, entityResource) {
    
        if(!$scope.control.value || $scope.control.value == undefined)
        {
            $scope.control.value = {};
            $scope.control.value.config = {};
            $scope.thumbnail = '';
        }
        else {
    
            // if existing scope has no image, create empty object
            if ($scope.control.value.image == '' || $scope.control.value.image == undefined) {
                $scope.thumbnail = '';
                $scope.control.config
                $scope.control.value.config = { width: 0, height: 0 };
            }
            else {
                // if we have a image id, call information about media item using media resource
                entityResource.getById($scope.control.value.imageId, "Media").then(function (ent) {
                    console.log(ent);
                    $scope.thumbnail = ent.metaData.umbracoFile.Value;
                    $scope.control.value.config = { width: ent.metaData.umbracoWidth.Value, height: ent.metaData.umbracoHeight.Value };
                });
            }
        }
    
        // Select an image
        $scope.pickImage = function () {
            // open the built-in mediapicker
            dialogService.mediaPicker({
                multiPicker: false, // only allow one image to be picked
                // function that is called when the dialog is closed. 
                // Selected item(s) will be passed in by the data object
                callback: function (data) {
                    $scope.control.value.image = data.image;
                    $scope.control.value.imageId = data.id;
                    $scope.thumbnail = data.thumbnail;
                    $scope.control.value.config = { width: data.originalWidth, height: data.originalHeight };
                }
            });
        };
    
        // Select a content node to link to, OR enter a URL to an external site, very similar to pickImage()
        $scope.pickContent = function () {
            dialogService.linkPicker({
                multiPicker: false,
                section: "content",
                treeAlias: "content",
                callback: function (data) {
                    $scope.control.value.link = { name: data.name, id: data.id, url: data.url, target: data.target };
                }
            });
        };
    
        // Remove the selected content or entered link
        $scope.removeContent = function () {
            $scope.control.link = undefined;
        };
    });
    

    The backend/grid view (LinkImage.html)

    <div id="simple-control.valuer-list-editor" ng-controller="LinkImage.controller">
    <div class="usky-editor-placeholder" ng-click="pickImage()" ng-if="!control.value.image">
        <i class="icon icon-picture"></i>
        <div class="help-text"><localize key="grid_clickToInsertImage">Click to insert image</localize></div>
    </div>
    
    <div ng-if="control.value.image">
        <img ng-if="control.value.image"
             ng-click="pickImage()"
             ng-src="{{control.value.image}}"
             class="fullSizeImage" />
        <input type="text" class="caption" style="width:100%; border:none; font-style:italic;" ng-model="control.value.caption" localize="placeholder" placeholder="@grid_placeholderImageCaption" />
    </div>
    <br/>
    <div>
        <i class="icon icon-add blue" ng-show="!control.value.link"></i>
        <a href ng-click="pickContent()" ng-show="!control.value.link">link</a>
        <a href ng-click="control.value.link = undefined" ng-show="control.value.link">
            <p ng-show="control.value.link.name">
                <i class="icon icon-delete red"></i>
                {{control.value.link.name}}
            </p>
            <p ng-show="control.value.link.url && !control.value.link.name">
                <i class="icon icon-delete red"></i>
                {{control.value.link.url}}
            </p>
        </a>
    </div>
    

    The frontend view (LinkImage.cshtml)

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<dynamic>
    @using Umbraco.Web.Templates
    @if (Model.value != null){
        if(Model.value.image != null && Model.value.image != ""){ 
            var url = Model.value.image;
        if (Model.value.config != null){
            url += "?width=" + Model.value.config.width;
            url += "&height=" + Model.value.config.height;
        }
        if(Model.value.link != null)
        { 
            <a href="@Model.value.link.url" target="@Model.value.link.target"><img src="@url" alt="@Model.value.caption" /></a>
        }
        else
        {
            <img src="@url" alt="@Model.value.caption" />
        }
    
        if (Model.value.caption != null)
        {
            <p class="caption">@Model.value.caption</p>
        }
    }
    }
    

    This is fairly easy to customize to your needs :)

    And finally, the package manifest (package.manifest)

    {propertyEditors: [
        {
            name: "Link Image",
            alias: "linkimage",
            editor: {
                view: "~/app_plugins/linkimage/linkimage.html",
                valueType: "JSON"
            }
        }
    ],
    javascript: ['~/App_Plugins/LinkImage/LinkImage.controller.js']}
    

    When all the files are in order, you simply need to tell Umbraco to allow it in the grid, by going into /Config/grid.editors.config.js, and adding:

    {
        "name": "Link Image",
        "alias": "linkimage",
        "view": "/App_Plugins/LinkImage/LinkImage.html",
        "icon": "icon-link"
    }
    

    It ends up looking like this (with and without a picture selected)

    ImageLink

    With a link dialog like this

    enter image description here

    Now, if there are any errors or redundancies in my code, I'm sure it'll come up - again, I'm fairly new, but it has worked for me, and thought I'd share, for people who just happen to need a link image :)

  • Rune Hem Strand 146 posts 903 karma points hq c-trib
    Aug 27, 2015 @ 21:58
    Rune Hem Strand
    0

    Hi Eric

    When you have the editor view linkimage.html in the plugins folder ~/app_plugins/linkimage/ you can put the the render view (with the same name) linkimage.cshtml in the same folder and it will be detected automatically. You can also specify a render path by adding render in the editor definition:

    {
       gridEditors: [
          {
              name: "Link Image",
              alias: "linkimage",
              view: "~/app_plugins/linkimage/linkimage.html",
              render: "~/app_plugins/linkimage/linkimage.cshtml"
          }
      ],
      javascript: ['~/App_Plugins/LinkImage/LinkImage.controller.js']
    }
    

    In the image you posted it looks like the controller is is not initialized in the view but hard to figure out why without more info :)

    You can read more about the making grid editors here.

    There is also some videos about it on umbraco.tv

    /Rune

  • Eric Schrepel 150 posts 203 karma points
    Aug 27, 2015 @ 22:02
    Eric Schrepel
    1

    It was a minor file capitalization thing. My bad, works great now, thanks.

    Working on tweaking the "link" because often, all the image needs to do is link to a larger (original size) version of itself. It'll give me something to learn as I try to get it working :)

  • Rune Hem Strand 146 posts 903 karma points hq c-trib
    Aug 27, 2015 @ 22:12
    Rune Hem Strand
    0

    Great you got it working :)

    #h5yr

  • Jonathan 6 posts 39 karma points
    Nov 21, 2015 @ 18:50
    Jonathan
    1

    BUMP.

    Thanks for sharing this, it was crucial in helping me fill in some gaps for a problem I've been banging my head on.

    I've come to believe that having a high degree of proficiency in building custom property editors is the key to delivering the sort of interfaces clients demand.

  • Jan Borup Coyle 6 posts 30 karma points
    Aug 30, 2019 @ 13:07
    Jan Borup Coyle
    0

    Please HELP !!!

    I have tried for some hour now to solve a problem with this.

    I have created the files, in the /App_Plugins... but when running my site without creating any LinkImage i got this error in the Bootstrap3.cshtml :

    'string' indeholder ikke en definition til 'sections'

    Beskrivelse: Der opstod en undtagelse, der ikke blev behandlet, under udførelse af den aktuelle webanmodning. Se staksporingen for at få flere oplysninger om fejlen, og hvor den kom fra i koden.

    Detaljer om undtagelse: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'string' indeholder ikke en definition til 'sections'

    Linje 7:  *@
    Linje 8:  
    Linje 9:  @if (Model != null && Model.sections != null)
    Linje 10: {
    Linje 11:     var oneColumn = ((System.Collections.ICollection)Model.sections).Count == 1;
    

    Kildefil: c:\Work\csn-v41\Chainbox.App.Webshop\Views\Partials\Grid\Bootstrap3.cshtml Linje: 9

    I'm running this on a Umbraco 7.4.3

    Any clues ?

    Best regards Jan Borup Coyle

Please Sign in or register to post replies

Write your reply to:

Draft