IMG_3739

 

It’s been a little more than a month since Umbraco 7 was released and it feels like a great timing that we announced new dates for Umbraco training in Stockholm, Sweden. Just like last time the course will be in Swedish but the course material (slides and workbook) is in English.

 

Please read more about the training here: /vi-erbjuder/utbildning-umbraco.aspx (in Swedish)

One requirement of Enkel Medias Umbraco-package Newsletter Studio is to render and use the built in rich text editor from Umbraco (TinyMCE) in the custom Newsletter Studio-section.

 

Newsletter Studio -banner -580x 250

 

TinyMCE in a custom Umbraco 7-section

 

 

image

Since the backoffice of Umbraco 7 is rebuilt using AngularJS all property editors are built using JavaScript and they also rely on the current AngularJS-scope to contain some information on how to render the control. So in order to render our rich text editor (rte) we need to provide this information.

 

There are some different ways to render the control, some are more “hacky” than others and I’m going to walk you through some options. Just to be clear –this is not a best practice guide for JavaScript so I’ve added the JavaScript controllers in script-elements inside the views. This is something that you should not do, they should live in their own .js-files – but for simplicity I ignore that in this blog post.

 

Option 1 –Copy the original view

The first option is to just copy the code from the original rte-view (from the Umbraco source code). It looks something like this:

<div ng-controller="Umbraco.PropertyEditors.RTEController" class="umb-editor umb-rte">
    <textarea ng-model="model.value" rows="10" id="{{model.alias}}_rte"></textarea>
</div>

This is super simple. But it won’t work. Since Umbraco loads information about all the tabs, content, property types, values and so on for a content page when it’s loaded the RTEController assumes that the current scope has all this information. So we need to simulate that with our own controller. Let’s change the view so it looks like this:

<div ng-controller="CustomSectionEditController">    
    <ng-form>
        <div ng-controller="Umbraco.PropertyEditors.RTEController" class="umb-editor umb-rte">
            <textarea ng-model="model.value" rows="10" id="{{model.alias}}_rte"></textarea>
        </div>            
        <pre>
            Value from the RTE {{model.value}}
        </pre>
    </ng-form>
</div>

And for this code we need a controller called “CustomSectionEditController”, let’s just add a simple version of this controller:

<script type="text/javascript">
    function CustomSectionEditController($scope) {

        $scope.model = {
            alias: 'myRichtexteditor',
            config: {
                editor: {
                    toolbar: ["code", "undo", "redo", "cut", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbmacro", "table", "umbembeddialog"],
                    stylesheets: [],
                    dimensions: { height: 400, width: 250 }
                }

            }
        };
    }
</script>

With this code in place the rich text editor (rte) should be rendered and the HTML from the editor will be populated into the $scope.model.value-property.

 

While this works it’s not so very flexible and another problem is that it will be hard to “lazy load” properties, values and settings since the rendering of the rte-controller could start before all your data has been downloaded.

 

Option 2 – Use the umb-editor directive

In the views in Umbraco all the property editors are loaded dynamically the view for editing content only uses this simple tag:

<umb-editor model="myProperty"></umb-editor>

Umb-editor is a Umbraco-specific AngularJS directive that will look at the model attribute to find out which $scope-property to use for getting rendering information, in this case it’s $scope.myProperty – so let’s add that:

<script type="text/javascript">
    function CustomSectionEditController($scope) {
        $scope.myProperty= {
            label: 'bodyText',
            description: 'Load some stuff here',
            view: 'rte',
            config: {
                editor: {
                    toolbar: ["code", "undo", "redo", "cut", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbmacro", "table", "umbembeddialog"],
                    stylesheets: [],
                    dimensions: { height: 400, width: 250 }
                }
            }
        };
    }
</script>

As you can see with this code the $scope.myProperty.view property is called “rte” which tells AngularJS to load the rte (rich text editor)-view as the current view for this umb-editor. If we were to set $scope.myProperty.view to ‘textbox’, a textbox would be loaded. Updating the view to look like this would get this code to run:

<div ng-controller="CustomSectionEditController">    
    <ng-form>
        <umb-editor model="myProperty"></umb-editor>      
        <pre>
            Value from the RTE {{myProperty.value}}
        </pre>
    </ng-form>
</div>

This is a little bit cleaner than the approach in option 1 but we still suffer from the problem that the directive could be processed before we have loaded all our external data. For example – we would probably like to set the $scope.myProperty.value to some value that's loaded from the backend –but with this approach the directive could be processed before that data is downloaded and we’ll be left with a ugly error message.

 

Option 3 – Use ng-repeat and an array to “lazy load”

As far as I have seen this is the best way to load data from the backend and then render the wysiwyg-editor. In my use case I want to have a specific data type configured and when the page loads I want to get the configuration (pre values) for that data type and put that data in $scope.myProperty.config. I also want to download some content from the backend and put that in $scope.myProperty.value.

So – How do we avoid the directive from being processed before the data is loaded? A loop. Let’s put this in our view

<umb-property 
    property="property"
    ng-repeat="property in properties">
    <umb-editor model="property"></umb-editor>
</umb-property>

And then put an array of properties on the scope:

$scope.properties = [{
                        label: 'bodyText',
                        description: '',
                        view: 'rte',
                        config: {
                            editor: {}, // empty for now
                            hideLabel: true
                        }, hideLabel: true
                    }];

This would look almost the same as option 2 but. Since the ng-repeat attribute is there the directives will be reprocessed each time the $scope.properties-property change and since $scope.properties is null until after the data is downloaded the umb-editor directives will note be loaded.

 

The full view could look something like this:

<div ng-controller="CustomSectionEditController">    
    <ng-form>
        <umb-property 
            property="property"
            ng-repeat="property in properties">
            <umb-editor model="property"></umb-editor>
        </umb-property>
        <pre>
            Value from the RTE {{properties[0].value}}
        </pre>
    </ng-form>
</div>

And the controller like this:

<script type="text/javascript">
    function CustomSectionEditController($scope) {
        $scope.property = {
            label: 'bodyText',
            description: 'Load some stuff here',
            view: 'rte',
            config: {
                editor: {
                    toolbar: ["code", "undo", "redo", "cut", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbmacro", "table", "umbembeddialog"],
                    stylesheets: [],
                    dimensions: { height: 400, width: 250 }
                }
            }
        };
    }
</script>

Now the last step would be to make sure that the text-value for the editor is fetched from some backend service.

<script type="text/javascript">
    function CustomSectionEditController($scope, $http) {
        $http({ method: 'GET', url: '/url/to/our/cool/service' })
            .success(function (data) {
                $scope.property = {
                    label: 'bodyText',
                    description: 'Load some stuff here',
                    view: 'rte',
                    config: {
                        editor: {
                            toolbar: ["code", "undo", "redo", "cut", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbmacro", "table", "umbembeddialog"],
                            stylesheets: [],
                            dimensions: { height: 400, width: 250 }
                        }
                    },
                    value: data
                };

            })
            .error(function () {
                $scope.error = "An Error has occured while loading!";
            });
    }
</script>

As you can see we added the $http-parameter to the controller and uses it to fetch the data that we need before assigning the values to the scope. This will prevent the umb-editor directive from starting to load before all our data is loaded.

 

This is how I’ve solved the this issue at the moment and there may be other ways as well, please feel free to post questions or comments here below.

 

Cheers!

In the last post we talked about how to add a new custom application (or section) and a new custom tree to your Umbraco 7 backoffice. Now I’ll show you how to add views so that your sections can do something meaningful.

 

You could use legacy views as well but since I was rewriting Newsletter Studio to work use AngularJS and work really nice with Umbraco 7 I took this approach.

 

Newsletter Studio -banner -580x 250

 

 

The routing

Since we added the PluginController(“CustomSection“)-attribute to our tree-class, Umbraco will route the cliend side requests to a folder in the app_plugins-folder. The logic is something like: /app_plugins/{applicationName}/{treeAlias}/{action}/itemId so in our case we’re looking at the url /#/CustomSection/CustomSectionTree/edit/dashboard and Umbraco will look for /app_plugins/customsection/backoffice/CustomSectionTree/edit.html to show as the view – so let’s create that file.

 

The view

Add this content to our new edit.html-file:

<script>

    function CustomSectionEditController($scope, $routeParams) {
        $scope.content = { tabs: [{ id: 1, label: "Tab 1" }, { id: 2, label: "Tab 2" }] };

        $scope.EditMode = function() {
            return $routeParams.create == 'true';
        };
    }
</script>

<div ng-controller="CustomSectionEditController">

    <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>

 

This code will give us a view that looks like this:

 

image

 

Even if we could have added regular HTML in the view, I choose to include some AngularJS-stuff and some stuff that Umbraco adds on to AngularJS. The umb-tab, umb-tab-view, umb-panel-elements are something called directives which is a core concept in AngularJS. These directives hide complex logic for generating the view that’s on the right and side of our backoffice. Directives are very powerfull and can be used to create reusable code and "widgets" in your application – let’s just ignore the details of this for now and focus on the code above.

 

In the script-tag I create a regular JavaScript function that will act as the controller for the view, this function take a $scope-variable as parameter which will act as the "glue" between the controller and the view. $scope is a funamental part of AngularJS and should be familiar to you if you have worked with Angular before. Since the Umbraco's custom directives looks at the $scope.content.tabs-property when creating the tabs we need to populate this property with some static data – in this case the “Tab 1” and “Tab 2”-objects.

 

The only “magic” that you’ll need to be aware of is that Umbraco will match the id of the tab with the id of the <umb-tab>-tag. So <umb-tab id="tab1"> will be showed when you click the tab with id 1 – and <umb-tab id="tab2"> will be showed when you click the tab with id 2. Let’s look closer at the $routeParams and the CreateAction that we added to the TreeController-class in the last post.

 

The menu items

The MenuItemCollection, that the TreeController we created in the last post, returns a collection that just contains a ActionNew-item. This action will look for the view /app_plugins/CustomSection/Umbraco/CustomSectionTree/create.html which will be displayed when the user clicks the “Create new” button.

 

image

 

I have use some code from the create content-dialog – lets add this to our create.html-view.

<div class="umb-dialog-body with-footer">
    <div class="umb-pane">
    <h5><localize key="create_createUnder">Create something under </localize> {{currentNode.name}}</h5>

    <ul class="umb-actions umb-actions-child">
        <li>            
            <a href="#/CustomSection/CustomSectionTree/edit/dashboard?create=true" ng-click="nav.hideNavigation()">
                <i class="large icon-car"></i> 
                <span class="menu-label">New custom item
                    <small>Click here to create this super custom item</small>
                </span>
            </a>
        </li> 
    </ul>
    </div>        
</div>
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
        <button class="btn" ng-click="nav.hideDialog()">
            <localize key="buttons_somethingElse">Do something else</localize>
        </button>
</div>

 

Yesterday we finally got the the first release of Umbraco 7 which introduce a new look and feel for the backoffice. Not only that – the technicall differences from V6 is huge.

 

Since I'm writing the popular newsletter-package Newsletter Studio for Umbraco I had look really deep into the source of Umbraco 7 to get things right.

 

Newsletter Studio -banner -580x 250


I now want to show you how to add a custom section with a custom tree to the Umbraco backoffice – some of the things is similar to how it used to work (in V4-6) and some things are new.

 

Creating the application

Every section in Umbraco is called an application, so sections and applications is basically the same thing.The first thing we’ll need to do is to create the application. In this examples I will not fiddle with the xml-files or the database – I’ll use class annotations to create my section.

The first thing I’ll need to do is to create a class that implements the IApplication-interface so that Umbraco will initialize this class on start up.

 

[Application("CustomSection", "CustomSection","icon-car", 15)]
public class CustomSectionApplication : IApplication {}

 

This is not something new for V7, The "Application"-attribute basically tells Umbraco to create a new application:
Name: CustomSection
Alias: CustomSection
Icon: icon-car (the css class for the icon that will be displayed in the left side bar of the backoffice)
Sort order: 15

The next time Umbraco runs it will add an XML-element to the /config/applications.config-file that will add our new section/application to the Umbraco backoffice.

 

Creating the tree

Before adding the tree, Umbraco will not care about your new application. An application without a tree is not worth anything =D Right?

This part contains some new concepts for V7. Let's start with creating a new class that inherits from Umbraco.Web.Trees.TreeController, make sure to suffix the class name with “Controller” ie. CustomSectionTreeController.

public class CustomSectionTreeController : TreeController
{
}

 

Now we need to give Umbraco some extra information about our tree. Let's add two attributes on the class, the Tree and the PluginController-attributes.

[PluginController("CustomSection")]
[Umbraco.Web.Trees.Tree("CustomSection", "CustomSectionTree", "My custom section", iconClosed: "icon-doc")]
public class CustomSectionTreeController : TreeController
{
}

 

PluginController

This attribute tells Umbraco that this class is part of a plugin, and it also tells Umbraco the name of that plugin. This will make Umbraco look for views inside the /app_plugin/{NameOfApplication}/-folder and not in the folder of the core-views which is the default.

 

Tree

This attribute is “older” and has been around since somewhere around 4.7 I think. It tells Umbraco that this is a tree-class and Umbraco will add this to the /config/trees.config-file. In V7 this attribute is mandatory for a tree that inherits from the TreeController-class as some underlying logic is looking at the attribute values to determine the name of the tree.

 

The properties are:
Application: CustomSection (must match the name of the application we added before)
Alias: CustomSectionTree (the name/alias of the tree)
Title: The title of the tree (used as the name of the root node)
Icon: The icon (or class) used as the tree icon.

 

Alright. Almost there. Now we need to add some code to show items in the tree.

[PluginController("CustomSection")]
[Umbraco.Web.Trees.Tree("CustomSection", "CustomSectionTree","My custom section", iconClosed: "icon-doc")]
public class CustomSectionTreeController : TreeController
{
    protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
    {
        var nodes = new TreeNodeCollection();
        var item = this.CreateTreeNode("dashboard", id, queryStrings, "My item", "icon-truck", true);
        nodes.Add(item);
        return nodes;
    }

    protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
    {
       var menu = new MenuItemCollection();
       menu.DefaultMenuAlias = ActionNew.Instance.Alias;
        menu.Items.Add<ActionNew>("Create");
        return menu;
    }
}

 

This will give us something like this:

 

image

 

This code has two methods that are the least we need to do to create a new section.

 

GetTreeNodes (TreeNodeCollection)

This returns a collection of tree items, in our case we just return one item but we could of curse add more items to the collection. We use the CreateTreeNode-method from the base class to create a new node called “My item” with the id “dashboard”. Umbraco will append the id of the node to the URL later on so that we can handle the routing from our AngularJS-controllers.

 

GetMenuForNode (MenuItemCollection)

imageThis method handles the “right click alternatives”. The “DefaultMenuAlias” configures which action that should be fired when we click the “touch dots” .

 

There's a lot of actions that you can use and you can also build your own ones.

 

image

 

Displaying our new section

To display our new section we need to give the current user access to it. Go to the users-section and open the edit-view for the current logged on user. In the bottom, check the checkbox for [CustomSection] and hit save. Now you’ll probably need to refresh the page using F5 to show the new section in the left side bar.

 

Making the [CustomSection]-text look better

Since Umbraco can’t find any language translation for our section it will use the brackets and the application name. To make this nicer, open the /umbraco/config/lang/en.xml-field and look for the <area alias=”sections”>-element. Inside that element, just add:

 

<key alias="CustomSection">Super Custom Section</key>

 

image

 

You may need to touch the root web.config file to restart the application before the new translation gets visible.

 

This is my first blog post about custom sections and custom trees in Umbraco 7 – next time I’ll you show how you can create the views for the new tree items.

After weeks of hard work from the guys in the core team Umbraco 7 was released today! The biggest news is the new look and feel of the backoffice.

 

dashboard

 

If you have used Umbraco before you’ll probably find your way around as the over all concepts are the same. If you know how to build websites with previous versions of Umbraco you’ll feel comfortable with V7 as well. The new backoffice has been built with the editors in mind and I must say that we’re seeing a lot of improvements! I really love the why that the people behind the design is thinking.

 

I’ve looked at the beta and RC-versions of V7 and provided some feedback (ie. the drag and drop into the media dialog) and I really recommend you to download the latest version and play with it! Start building your new sites with it! But it’s important to don’t leave your frustrations in your mind – share them at issues.umbraco.org so that the core team can do something about it! It’s the least each and everyone can do to contribute to this great project!

 

Niels Hartvig posted a nice video of the new backoffice, have a look at it here: http://umbraco.com/follow-us/blog-archive/2013/11/21/umbraco-7.aspx

Last week I hosted the first Umbraco Training Courses in Sweden. We now have more than 20 new certified Umbraco developers and some new companies have become Certified Partners.

 

Since it was my first course I can admit that I was a little bit nervous i the beginning of the week – I always get that feeling when stepping out of my “comfort zone” and doing something that I have never done before. So far I have only got good feedback from the attendees, some even called me “excellent” – thank you very much for that. =D

 

I’ve been asked if we are going to have a new round of training in Sweden. Of course! But we have not decided the exact dates yet. If you want to be noticed – sign up for our newsletter.

 

 

I also would like to share to share some photos from the course =D

 

level1

Level 1 attendees working on one of the exercises.

 

level2-book

The Level 2 workbook, razor-sheet sheet and the super fancy Umbraco USB that all attendees got a copy of.

 

level2-grupp

Attendees at the level 2 course.

 

level2-grupp2

Closest in this picture we see attendees from Chalmers in Gothenburg and from the Örebro-based company Impera

feature-datatypeI you’re a long time reader of this blog you know that I’m working hard with my newsletter-package for Umbraco – Newsletter Studio.

Today I announced some news that I hope will make some of all the web agencies out there happy. As web agencies over the world will all get a free Newsletter Studio license for their own website.

So if you your company web site runs on Umbraco, don’t wait – request your free license today!

I’m back in Sweden after a great weekend in the Netherlands. Last Friday was all about Umbraco as the local user group DUUG (Dutch Umbraco User Group) was throwing an Umbraco Festival.

 

There were a lot of great sessions to watch, for example Niels Hartvig showed the latest about the Umbraco Concord (or Umbraco as a service) project which looks really really good! Also Jeavon Leopold (@crumpled_jeavon) and Jeroen Breuer (@j_breuer) hosted a nice framework session on there Umbraco Framework project: https://github.com/jbreuer/Hybrid-Framework-Best-Practices

 

Me and some other package vendors spent a lot of time in the vendors booths showing our packages for the visitors.

 

duug-soren

Here I am with the uCommerce-guy Søren Spelling Lund (@publicvoid_dk)

 

duug-keynote

Just before the keynote that was held by Niels Hartvig (@umbraco)

 

duug-people 

Some loaded Umbracians waiting for more sessions.

 

 

I also had the chance to host my own session about the Newsletter Studio-package.

 

duug-speech1

 

duug-speech2

 

duug-speech3

 

duug-speech4 

 

duug-speech5

 


A very big thank you to the DUUGs-people and Richard Soeteman for inviting me over! And thank you very much to everyone who attended my session!

 

If you are looking for Umbraco speakers for your local event, don’t hesitate to contact me, by e-mail, on twitter: @enkelmedia or on skype: enkelmedia

English readers: Sorry - This is between me and the " swedes"=D


Det var ett tag sedan som jag skev ett inlägg på svenska men jag kände att det var dax. I början av förra veckan blev det officiellt att jag, från och med denna höst, kommer att leda de svenska Umbraco-utbildningarna.


Det känns riktigt stort och väldigt roligt!

 

umnbracooo


När jag hörde om Umbraco första gången i slutet av 2007 så tyckte jag först att det var ett krångligt och "svårgreppat" system. Kanske för att man var tvungen att ha koll på XSLT vilket jag inte hade då. Jag tror att det som lockade mig med detta CMS var att det lät mig ha full kontroll över den genererade HTML-koden. Det här var i en tid då jag precis hade fått lära mig att vi utvecklare inte skulle skriva HTML, CSS och JavaScript - allt skulle göras med ASP.NET-kontroller, det skulle bara vara att dra och släppa. Vi som varit med sedan Klassisk ASP-tiden skulle glömma allt vi visste - vi skulle upp en abstraktionsnivå.


Jag behöll lite av min förkärlek till grunderna för webben vilket har visats sig vara ett bra drag. Idag skämtar många om den kod som de tidigare generationerna av ASP.NET WebForms genererade. Idag handlar mycket om att "gå tillbaka till kärnan" och verkligen bejaka http-protokollet och webbens grundstenar.


För mig är inte det är något nytt. Umbraco CMS har låtit mig göra detta ända sedan jag upptäckte det 2007. Idag kan man till och med välja mellan WebForms och MVC som grund i sin sajt och senare i höst kommer ett helt nytt backoffice (Bella aka. Umbraco 7) som är byggt i JavaScript med AngularJS. Umbraco ger mig möjlighet att skräddarsy mina projekt efter kundernas behov och de får ett system som de verkligen kan växa med.


Det händer en hel del spännande med Umbraco CMS och jag vill verkligen tipsa dig och dina kollegor om hösten kurser där du snabbt och enkelt kommer "up to speed" med både grunderna och nyheterna i Umbraco.

 

Läs gärna mer om dem och tveka inte att höra av dig om du har några frågor eller funderingar.

Today I had problems with logging in to my newly installed SQL Server instance. During the install i choose “Windows mode” but I did mange to mess up which user that has access to SQL Server. I tried to start up in Single user mode which did not work, but I found this blog post that had a great solution:

 

http://www.mssqltips.com/sqlservertip/2682/recover-access-to-a-sql-server-instance/

 

sql-server-loggon

 

Basically these steps:

 

1. Install PSExec

2. Open the command line with “Run as administrator”

3. Run this command:  PsExec -s -i "C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\Ssms.exe"

 

This will open SQL Server Management Studio as the NT AUTHORITY\SYSTEM-account which has all the privileges needed.