Nibble

Autobots, Roll out! Optimus 1.2.0 Release with Umbraco v7 Compatibility is available 4

Like I mentioned during the Uk fest, adding v7 support to your packages is easy Smile (the hard part was writing this blog post)

So I’m glad to announce a new release of Optimus

If you haven’t seen it in action be sure to check out this 5 minute show and tell

If you don’t have 5 minutes to spare here are some screenshots
OptimusBundlerOptimusBundleEditorOptimusBundleFileEditor

Special thanks to Jeavon Leopold for all the hard work! If you are looking for someone to build your Umbraco site make sure to check http://www.crumpled-dog.com/

Advanced property editors for Umbraco v7, Validation 0

Look at the following example prop editor (it’s basically a port of the sample todo app on the http://angularjs.org/ homepage, a bit simplified to focus on the important bits)

image

So in this case the prop editor contains a form that will add items to a array/list

The controller

angular.module("umbraco").controller("SampleValidationController",
        function ($scope) {
 
         if(!(Object.prototype.toString.call($scope.model.value) === ‘[object Array]’)){
             $scope.model.value = new Array();
         }
 
         $scope.addTodo = function() {
            $scope.model.value.push({text:$scope.todoText, done:false});
            $scope.todoText = ;
          };
 
        });

The View

 <div ng-controller="SampleValidationController">
 
         <ul class="unstyled">
           <li ng-repeat="todo in model.value">
             <input type="checkbox" ng-model="todo.done">
             <span class="done-{{todo.done}}">{{todo.text}}</span>
           </li>
         </ul>
         <form ng-submit="addTodo()">
           <input type="text" ng-model="todoText"  size="30"
                  placeholder="add new todo here">
           <input class="btn-primary" type="submit" value="add">
      </form>
 
 </div>

Of course when people click the add we want to make sure not to add an empty item to the list….

So the easiest would be to add a required attribute to the text input.. that works

image

but doing that will interfere with the page publish

image

And that’s not what we want… so the validation only needs to happen when we hit the add not publish…

So we’ll need to create a variable in our controller that will hold the validation state (initially set this to false and the manually check if we want to proceed and change the value of the validation state…)

angular.module("umbraco").controller("SampleValidationController",
        function ($scope) {
 
        $scope.hasError = false;
 
         if(!(Object.prototype.toString.call($scope.model.value) === ‘[object Array]’)){
             $scope.model.value = new Array();
         }
 
         $scope.addTodo = function() {
            if($scope.todoText)
            {
                $scope.model.value.push({text:$scope.todoText, done:false});
                $scope.todoText = ;
                $scope.hasError = false;
            }
            else
            {
                $scope.hasError = true;
            }
          };
 
        });

 

In our view we can now use a custom directive to show a bit of feedback to the user val-highlight="hasError" (of course passing in the variable name) and getting rid of the required

<input type="text" ng-model="todoText"  size="30"
                  placeholder="add new todo here" val-highlight="hasError">

So now when I try to hit the add without filling in a value I’ll get a red border for a couple of seconds

image

And we don’t interfere with the page publish validation…

Advanced property editor for Umbraco v7, working with custom data 0

These prop editor posts just keep coming Winking smile

Is this one I’ll outline how to fetch some third party data in your prop editor

So first I’ll need to expose some data using an API controller

    [PluginController("Contour")]
    public class FormsApiController : UmbracoAuthorizedJsonController
    {
        public IEnumerable<Models.Form> GetAll()
        {
            var forms = new List<Models.Form>();
            FormStorage s = new FormStorage();
 
            foreach (var form in s.GetAllForms(false))
            {
                if (UI.Security.HasAccessToForm(form.Id))
                {
                    Models.Form f = new Models.Form();
                    f.Id = form.Id;
                    f.Name = form.Name;
                    f.Fields = GetFormFields(form);
                    forms.Add(f);
                }
            }
            s.Dispose();
 
            return forms;
        }
}

Notice that I’m using an UmbracoAuthorizedJsonController to make sure only logged in Umbraco backoffice users have access…

Then I’m simply returning a list of Forms (forms is a custom model that looks like)

 public class Form
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Fields { get; set; }
    }

So I’m using Contour to fetch all forms (but since those have to much data I’m creating them as my simple form object) and then returning them a a list.

So that’s the api controller done,

Next is the angular controller

angular.module("umbraco").controller("Contour.FormPickerController",
        function ($scope, $http) {
            $scope.loading = true;
            $http({ method: ‘GET’, url: ‘Contour/FormsApi/GetAll’ })
                .success(function (data) {
                    $scope.forms  = data;
                    $scope.loading = false;
                })
                .error(function () {
                    $scope.error = "An Error has occured while loading!";
                    $scope.loading = false;
                });
        });

So it does a get request of Contour/FormsApi/GetAll (that is where we’ll find our api controller method since this is auto routed) and assigns the result to $scope.forms

And the final bit, the view looks like

 <div ng-controller="Contour.FormPickerController">
     
     <div class="radio" ng-repeat="form in forms">
         <label>
             <input ng-model="model.value" value="{{form.Id}}" type="radio" name="form">
             {{form.Name}}
             <small>{{form.Fields}}</small>
         </label>
     </div>
 
 </div>

So it’s just looping the form objects and outputting them as radiobuttons (setting model.value)

End result looks like

FormPicker

You’ll see that in this example the data is fetched async ideally I would also like to set a scope object on load, maybe that’s something for the next post Winking smile

Creating custom param editors in Umbraco v7 3

In v7 it’s super easy to create param editors (the type of control you can choose for macro params).

image

You can basically use all of the prop editor knowledge and just set a flag in the manifest to allow the prop editor to be used as param editor (if that Isn’t easy Smile )

Check the documentation for full details http://umbraco.github.io/Belle/#/tutorials/manifest

isParameterEditor enables the property editor as a macro parameter editor can be true/false

So to allow my sample prop editor http://www.nibble.be/?p=285 (char limit) to be used as a param editor all it takes is a little update of the manifest (and restart the app so the manifest changes are picked up)

{
    propertyEditors: [
        {
        alias: "Demo.CharLimitEditor",
        name: "Char limit",
        isParameterEditor: true,
        editor: {
        view: "~/App_Plugins/CharLimitEditor/charlimiteditor.html"
        },

And that’s it Smile

image

Advanced property editors for Umbraco v7 and XSLT 8

xslt

As you could see in the previous couple of posts, in umbraco v7 when creating a more advanced prop editor it will store it’s data as json. But what if you are still using xslt to output your property data to your frontend (yes there are still some folks around that prefer xslt, the sadomasochists of the Umbraco community)

Since json data is useless in xslt we added a new library method that you can use to convert json to xml Smile

<xsl:copy-of select="umbraco.library:JsonToXml($currentPage/matrix)"/>

 

In the case of the matrix prop editor you’ll end up with the following xml

<json>
<arrayitem>
    <arrayitem>xslt</arrayitem>
    <arrayitem>is</arrayitem>
</arrayitem>
<arrayitem>
    <arrayitem>not</arrayitem>
    <arrayitem>dead</arrayitem>
</arrayitem>
</json>

Advanced property editors for Umbraco v7, strongly typed values in your views using PropertyValueConverters 10

As you could see in the previous post, if we have a prop editor where the value type is set the JSON we can also iterate this in your razor views

<table>
<tbody>
@foreach(var row in CurrentPage.matrix)
{
<tr>
@foreach(var val in row)
{
<td>@val</td>
}
</tr>
            }
</tbody>
</table>

Of course the type of object in this case is dynamic but a little thing called PropertyValueConverters make it possible to convert this into a strongly typed object!

Here is an example implementation

    [PropertyValueType(typeof(Matrix))]
    [PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
    public class MatrixValueConverter : PropertyValueConverterBase
    {
        public override bool IsConverter(PublishedPropertyType propertyType)
        {
            return propertyType.PropertyEditorAlias.Equals("Nibble.MatrixEditor");
        }
 
        public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
        {
            if (source == null) return null;
            var sourceString = source.ToString();
 
            if (sourceString.DetectIsJson())
            {
                try
                {
                    var obj = JsonConvert.DeserializeObject<string[][]>(sourceString);
                    var matrix = new Matrix();
                    var rows = obj.Select(r => new Row {Values = r.ToList()}).ToList();
                    matrix.Rows = rows;
                    return matrix;
                }
                catch (Exception ex)
                {
                    return null;
                }
            }
 
            return sourceString;
        }
    }

That turns our json data into a custom Matrix object that looks like

    public class Matrix
    {
        public IEnumerable<Row> Rows { get; set; }
 
        public Matrix()
        {
            Rows = new List<Row>();
        }
    }

And the Row class looks like

    public class Row
    {
        public IEnumerable<string> Values { get; set; }

        public Row()
        {
            Values = new List<string>();
        }
    }

So now when I deploy this to my site when I fetch the value of a property that is using my custom matrix prop editor I’ll get an object of type Matrix Smile

If I then cast I get intellisense in Visual studio!

Intel

or you can also use Model.Content.GetPropertyValue<type>(“propAlias”)

More

Code for this is up on github https://github.com/TimGeyssens/MatrixPropEditor/tree/master/SamplePropertyValueConverter

Just a small gotcha, currently in the RC release you’ll have to remove the JSON value type from your custom prop editor if you want to attach a custom prop value convertor but that should be solved soon http://issues.umbraco.org/issue/U4-3591

Advanced Property Editors for Umbraco 7, important detail… 6

So yesterday I made the matrix prop editor for Umbraco 7 but I forgot an important detail. The prop editor works in the backoffice but when trying to output the values on the frontend I hit an error.

So you would expect this razor snippet to do the trick (in the case we have a prop called matrix)

<table>
<tbody>
@foreach(var row in CurrentPage.matrix)
{
<tr>
@foreach(var val in row)
{
<td>@val</td>
}
</tr>
            }
</tbody>
</table>

 

But when trying that I got the error Cannot implicitly convert type ‘char’ to ‘System.Collections.IEnumerable’

Since razor thought the data was a string…

To make sure razor knows the prop editor is storing json update the manifest to include the value type (standard it’s set to string)

editor: {
        view: "~/App_Plugins/MatrixEditor/matrixeditor.html",
        valueType: "JSON"
        },

More info on the options in the manifest can be found here http://umbraco.github.io/Belle/#/tutorials/manifest

So changing that makes the razor snippet work and I get the following output

<table>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
</tr>
</tbody>
</table>

 

When the content editor inputs

image

There is no spoon, Matrix Property Editor for Umbraco 7 0

You’ll love creating property editors in Umbraco V7!

If you haven’t tried it be sure to check out these resources for getting a quick start:
http://umbraco.github.io/Belle/#/tutorials/manifest
https://github.com/perploug/UkFest-AngularJS-Demo
http://www.nibble.be/?p=285

As a small experiment I thought it would be fun to see how fast a more complex prop editor would take to build. The goal was to build a configurable matrix editor (so define number of rows and cols as a setting and then let the content editor fill in the matrix). Turns Umbraco v7 prop editors make this really simple (of course you need some AngularJs knowledge since the new v7 backoffice is using that framework) but you don’t need any .net skills (and no more need to work with webforms like in previous Umbraco versions).

So after 30 mins of fiddling (mostly with creating a multi dimensional array) I have a working Matrix prop editor that looks like

MatrixEditor

And the settings look like

MatrixEditorSettings

All that was needed was 3 files

The manifest (defines the prop editor, alias, name, view, prevalues, js resources)

{
    propertyEditors: [
        {
        alias: "Nibble.MatrixEditor",
        name: "Matrix",
        editor: {
        view: "~/App_Plugins/MatrixEditor/matrixeditor.html"
        },
        prevalues: {
            fields: [
                {
                    label: "Number of columns",
                    description: "Enter the number of columns",
                    key: "cols",
                    view: "requiredfield",
                    validation: [
                        {
                            type: "Required" 
                        }                        
                    ]
                },
                {
                    label: "Number of rows",
                    description: "Enter the number of rows",
                    key: "rows",
                    view: "requiredfield",
                    validation: [
                        {
                            type: "Required" 
                        }                        
                    ]
                }                
            ]
        }
        }
    ]
    ,
    javascript: [
        ‘~/App_Plugins/MatrixEditor/matrixeditor.controller.js’
    ]
}

The view

<div ng-controller="Nibble.MatrixEditor">
     <table>
 
        <tbody>
            <tr ng-repeat="row in model.value">
                <td ng-repeat="col in row  track by $id($index)">
                     <input type="text" ng-model="row[$index]"></td>
            </tr>
        </tbody>
    </table>
</div>

And the controller

angular.module("umbraco")
    .controller("Nibble.MatrixEditor",
    function ($scope) {
 
 
         if (!$scope.model.value) {
            $scope.model.value = createArray(parseInt($scope.model.config.rows), parseInt($scope.model.config.cols));
         }
 
         function createArray(length) {
             var arr = new Array(length || 0),
                 i = length;
 
             if (arguments.length > 1) {
                 var args = Array.prototype.slice.call(arguments, 1);
                 while(i–) arr[length-1 - i] = createArray.apply(this, args);
             }
 
             return arr;
        }
 
    });

So you see this isn’t that much of code for a pretty complex property editor!

Sourcecode for this is on github https://github.com/TimGeyssens/MatrixPropEditor

Optimus, the 5 minute demo as seen at Umbraco UK Fest 2013 0

Wanna know more about Optimus check out http://www.nibble.be/?p=237

Optimus and Eazy D getting ready for Umbraco V7 0

With v7 just around the corner (RC went out yesterday http://umbraco.com/follow-us/blog-archive/2013/11/5/hello-umbraco-7-rc.aspx ) it’s a perfect time to test and update packages so they can also support Umbraco version 7!

Turns out this is pretty easy! I just need to do some final tests but thanks to the awesome work by Shannon and Per custom trees/actions/backoffice pages just work like they did on previous Umbraco versions. Also if you have custom webforms pages that use the umbraco UI controls you’ll get an instant v7 look!

Updating Optimus

Optimus consists of some custom trees, custom backoffice pages (some done in MVC some with webforms) and also an extension to the template editor.

Custom trees/backoffice pages all worked out of the box only changes I made was to change the icon in the tree and for the MVC pages I needed to change some markup so it blends in with the v7 style (ones using webforms just had the correct styling since I was making use of the Umbraco ui controls)

Only hard part about updating was a change to the template editor, the toolbar buttons are now part of the code editor so needed to target that control instead of the main toolbar (that has the save button).

OptimusV7RC

Updating Eazy D

Eazy D is basically an extension to the template editor so the same applies here, due to the menu changes I just need to target a different control for adding the button… and since the dialog is created with MVC I also changed some of the markup so it fits in the the V7 look and feel

EazyDV7

Sourcecode for both projects is available on github

Optimus:https://github.com/TimGeyssens/BundlingAndMinificationForTheMasses
Eazy D: https://github.com/TimGeyssens/EazyD

« Previous PageNext Page »