A guide to creating a property editor in Umbraco
This tutorial guides you through creating a property editor, integrating it with Umbraco's Data Types, AngularJS modules and its injector. Finally, it explains how we can test our property editor.
The steps we will go through in part 1 are:
This tutorial covers how to use AngularJS with Umbraco, so it does not cover AngularJS itself. To read about AngularJS, you can take a look at some of the resources here:
We will have a "Suggestions" Data Type in Umbraco. It is registered as a Data Type in the backoffice, and assigned to a Document Type. The Data Type can create and suggest values.
To begin with, let's create a new folder inside /App_Plugins
folder. We will call it Suggestions
.
If you do not have an /App_Plugins
folder, you can create it at the root of your project.
Next, we will create a Package Manifest file to describe what the plugin does. This manifest will tell Umbraco about our new Property Editor and allow us to inject any needed files into the application.
Create the file /App_Plugins/Suggestions/package.manifest
.
For more information about the package.manifest file, see the Package Manifest article.
Inside the package.manifest
file, we will add the following JSON to describe the Property Editor. Have a look at the inline comments in the JSON below for details on each bit:
You can also create a property editor with C# instead of defining it in a package.manifest
. Create a Suggestion.cs
file at the root of your project to register the editor this way.
As the above C#
code is adding the Property Editor, the package.manifest
file can be simplified like this:
Now, we will add 3 files to the /App_Plugins/Suggestions/
folder:
suggestion.html
suggestion.controller.js
suggestion.css
These will be our main files for the editor, with the .html
file handling the view, .js
file handling the functionality and the .css
file containing the stylesheet.
In the .html
file we'll add:
Optional
Add ng-readonly="readonly"
to the input
tag in order to make the property editor read-only.
In the .js
file, we'll add a basic AngularJS controller declaration
In the .css
file, we'll add:
Now our basic parts of the editor are done, namely:
The package manifest, telling Umbraco what to load
The HTML view for the editor
The controller for wiring up the editor with angular
The stylesheet for defining our data type styles
We will now restart our application. In the Document Type, add a new property called "Suggestion" and add to it the newly created property editor "Suggestions" and save it.
Now open the content item of that Document Type and there will be an alert message saying "The controller has landed", which means all is well.
We can now edit the assigned property's value with our new property editor.
Now, open the suggestion.controller.js
file and edit it so it looks like this:
Visit the Property Editors page for more details about extending this service.
Then update the HTML file with the following, where we add the id to the button:
Now, clear the cache, reload the document, and see the Suggestions Data Type running.
When we save or publish, the value of the Data Type is automatically synced to the current content object and sent to the server, all through the power of Angular and the ng-model
attribute.
Learn more about extending this service by visiting the Property Editors page.
In this tutorial, we will add a server-side API controller, which will query a custom table in the Umbraco database. It will then return the data to an angular controller + view.
The result will be a person-list, populated from a custom table. When clicked it will store the ID of the selected person.
The first thing we need is some data; below is an SQL Script for creating a people
table with some random data in it. You could also use https://generatedata.com for larger amounts of data:
Next, we need to define an ApiController
to expose a server-side route that our application will use to fetch the data.
For this, you can create a new class at the root of the project called PersonApiController.cs
In the PersonApiController.cs
file, add:
This is a basic API controller that inherits from UmbracoAuthorizedJsonController
. This specific class will only return JSON data and only to requests that are authorized to access the backoffice.
Now that we have a controller, we need to create a method, which can return a collection of people, which our editor will use.
So first of all, we add a Person
class to the My.Controllers
namespace:
We will use this class to map our table data to a C# class, which we can return as JSON later.
Now we need the GetAll()
method which returns a collection of people, insert this inside the PersonApiController
class:
Inside the GetAll()
method, we write a bit of code. The code connects to the database, creates a query, and returns the data, mapped to the Person
class above:
We are now done with the server side of things, with the file saved you can now open the URL: /umbraco/backoffice/My/PersonApi/GetAll
.
This will return our JSON data.
Now that we have the server side in place and a URL to call, we will set up a service to retrieve our data. As an Umbraco-specific convention, we call these services a resource, so we always indicate what services fetch data from the DB.
Create a new file as person.resource.js
and add:
This uses the standard angular factory pattern, so we can now inject this into any of our controllers under the name personResource
.
The getAll()
method returns a promise from an $http.get
call, which handles calling the URL, and will return the data when it's ready. You'll notice that the $http.get
method is wrapped inside umbRequestHelper.resourcePromise
, the umbRequestHelper.resourcePromise
will automatically handle any 500 errors for you which is why the 2nd string parameter is there - it defines the error message displayed.
We will now finally set up a new view and controller, which follows previous tutorials, so you can refer to those for more details:
So with all these bits in place, all you need to do is register the property editor in a package.manifest - have a look at the first tutorial in this series. You will need to tell the package to load both your personpicker.controller.js
and the person.resource.js
file on app start.
With this, the entire flow is:
The view renders a list of people with a controller
The controller asks the personResource for data
The personResource returns a Promise and asks the my/PersonAPI ApiController
The ApiController queries the database, which returns the data as strongly typed Person objects
The ApiController returns those Person
objects as JSON to the resource
The resource resolves the Promise
The controller populates the view
There is a good amount of things to keep track of, but each component is tiny and flexible.
The important part of the above is the way you create an ApiController
call to the database for your own data. And finally, expose the data to angular as a service using $http
.
For simplicity, you could have skipped the service part and called $http
directly in your controller. However, having your data in services it becomes a reusable resource for your entire application.
This is step 2 in our guide to building a Property Editor. This step continues work on the Suggestion Data Type we built in step 1, but goes further to show how to add configuration options to our editor.
An important part of building good Property Editors is to build something flexible, so we can reuse it many times, for different things. Like the Rich Text Editor in Umbraco, which allow us to choose which buttons and stylesheets we want to use on each instance of the editor.
An editor can be used again and again, with different configurations, and that is what we will be working on now.
There are two ways to add configuration to the Property Editor. If in the previous step you chose to create the property editor using a package.manifest
file, read the package.manifest
section below. If you have chosen the C#
variant, read the Csharp
part of the article.
To add configuration options to our Suggestion Data Type, open the package.manifest
file. Right below the editor definition, paste in the prevalues block:
So what did we add? We added a prevalue editor, with a fields
collection. This collection contains information about the UI we will render on the Data Type configuration for this editor.
The label "Enabled?" uses the "boolean" view. This will allow us to turn the suggestions on/off and will provide the user with a toggle button. The name "boolean" comes from the convention of all preview editors.
Same with the "Default value" label, it will provide the user with a textarea. The user can input a default value for the property editor that should be displayed when the property editor is blank.
To hide the property editor label, add the hideLabel
parameter in the editor
block:
Your package.manifest
file should now look something like this:
It is also possible to add configuration if you have chosen to create a property editor using C#. Create two new files at the root of your project and update the existing Suggestion.cs
file to add configuration to the property editor.
First create a SuggestionConfiguration.cs
file with three configuration options: Enabled?
, Default Value
, and Hide Label?
:
Then create a SuggestionConfigurationEditor.cs
file:
Finally, edit the Suggestion.cs
file from step one until it looks like the example below:
Save the file, rebuild the application and have a look at the Suggestions Data Type. You should see that you have one configuration option.
The next step is to gain access to our new configuration options. For this, open the suggestion.controller.js
file.
Let's add the isEnabled
functionality. Before the closing tag, we will add a getState
method:
Next, we'll add the defaultValue
functionality. When the $scope.model.value
is empty or null, we want to use the default value. To do that, we add the following to the start of the controller:
See what's new? The $scope.model.config
object. Also, because of this configuration, we now have access to $scope.model.config.defaultValue
which contains the configuration value for that key.
Your suggestion.controller.js
file should now look like:
Finally, we'll add the hideLabel
functionality. For this, we'll open the Suggestion.cs
file and override the GetValueEditor method with configuration as a parameter.
Your Suggestion.cs
file should now look like:
Save the files and rebuild the application. To access the configuration options, enable/disable the Enabled?
and Hide Label?
options. Additionally, you can set a default value in the Default Value
field and see the Suggestions Data Type at play.
This is step 3 in the Property Editor tutorial. In this part, we will integrate one of the built-in Umbraco Services. For this sample, we will use the notificationsService
to show a dialog with a custom view when you click in a textbox. The dialog will appear if the content is longer than 35 characters.
First up, we need to get access to the service. This is done in the suggestion.controller.js
, where we add it as a parameter:
To hook the service with the textbox, we will use the add
method of the notificationsService. This will be used to render our own view by setting the view property. We will also pass an args
object which contains the Property Value and a callback function that we are going to call from our notification.
The callback is used to return data to the editor.
Now that we have access to the editor events, we will trim the text to a length of 35.
Now let's edit the getSuggestion
method to call showNotification
on clicking Get Suggestions
button.
At this point your controller should look like this:
suggestion.html
package.manifest
We will add 2 files to the /App_Plugins/Suggestions/
folder:
notification.html
notification.controller.js
In the notification.html
, we'll add:
In the notification.controller.js
we will add:
Restart the application and either enter a suggestion longer than 35 characters or click on the Get Suggestions
button. When you do so and click in the textarea, you will be presented with a notification like this:
The notification object contains the args
object that we passed to the view in our suggestion.controller.js
. When we click the Yes
button in the notification, we use the callback function from the Suggestions controller. This function is executed in the scope of our Suggestions Property Editor.
Over the 3 previous steps, we have:
Created a plugin.
Defined an editor.
Registered the Data Type in Umbraco.
Added a $scope
object to pass information from the controller to the view.
Added configuration to the Property Editor.
Connected the editor with the Notification Service.
Looked at the notification dialog in action.