Fixed up the umbPropEditorHelper to ensure that the correct path is returned for views (because we can have relative views specified too). Moved angularhelper to it's own file, started on the DropDown property editor in c#.
This commit is contained in:
@@ -33,7 +33,10 @@ namespace Umbraco.Core.PropertyEditors
|
||||
public string Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The view to render for the field
|
||||
/// Defines the view to use for the editor, this can be one of 3 things:
|
||||
/// * the full virtual path or
|
||||
/// * the relative path to the current Umbraco folder
|
||||
/// * a simple view name which will map to the views/prevalueeditors/{view}.html
|
||||
/// </summary>
|
||||
[JsonProperty("view", Required = Required.Always)]
|
||||
public string View { get; set; }
|
||||
|
||||
@@ -34,25 +34,22 @@ namespace Umbraco.Core.PropertyEditors
|
||||
ValueType = "string";
|
||||
}
|
||||
|
||||
public PropertyEditorAttribute(string id, string name, string valueType, string editorView, string preValueEditorView)
|
||||
public PropertyEditorAttribute(string id, string name, string valueType, string editorView)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(id, "id");
|
||||
Mandate.ParameterNotNullOrEmpty(name, "name");
|
||||
Mandate.ParameterNotNullOrEmpty(valueType, "valueType");
|
||||
Mandate.ParameterNotNullOrEmpty(editorView, "editorView");
|
||||
Mandate.ParameterNotNullOrEmpty(preValueEditorView, "preValueEditorView");
|
||||
|
||||
Id = id;
|
||||
Name = name;
|
||||
ValueType = valueType;
|
||||
EditorView = editorView;
|
||||
PreValueEditorView = preValueEditorView;
|
||||
}
|
||||
|
||||
public string Id { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public string EditorView { get; private set; }
|
||||
public string ValueType { get; set; }
|
||||
public string PreValueEditorView { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,10 @@ namespace Umbraco.Core.PropertyEditors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The full virtual path or the relative path to the current Umbraco folder for the angular view
|
||||
/// Defines the view to use for the editor, this can be one of 3 things:
|
||||
/// * the full virtual path or
|
||||
/// * the relative path to the current Umbraco folder
|
||||
/// * a simple view name which will map to the views/propertyeditors/{view}/{view}.html
|
||||
/// </summary>
|
||||
[JsonProperty("view", Required = Required.Always)]
|
||||
public string View { get; set; }
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Some angular helper/extension methods
|
||||
*/
|
||||
function angularHelper($log, $q) {
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.angularHelper#rejectedPromise
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* In some situations we need to return a promise as a rejection, normally based on invalid data. This
|
||||
* is a wrapper to do that so we can save one writing a bit of code.
|
||||
*
|
||||
* @param {object} objReject The object to send back with the promise rejection
|
||||
*/
|
||||
rejectedPromise: function (objReject) {
|
||||
var deferred = $q.defer();
|
||||
//return an error object including the error message for UI
|
||||
deferred.reject(objReject);
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name safeApply
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This checks if a digest/apply is already occuring, if not it will force an apply call
|
||||
*/
|
||||
safeApply: function (scope, fn) {
|
||||
if (scope.$$phase || scope.$root.$$phase) {
|
||||
if (angular.isFunction(fn)) {
|
||||
fn();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (angular.isFunction(fn)) {
|
||||
scope.$apply(fn);
|
||||
}
|
||||
else {
|
||||
scope.$apply();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name getCurrentForm
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns the current form object applied to the scope or null if one is not found
|
||||
*/
|
||||
getCurrentForm: function (scope) {
|
||||
|
||||
//NOTE: There isn't a way in angular to get a reference to the current form object since the form object
|
||||
// is just defined as a property of the scope when it is named but you'll always need to know the name which
|
||||
// isn't very convenient. If we want to watch for validation changes we need to get a form reference.
|
||||
// The way that we detect the form object is a bit hackerific in that we detect all of the required properties
|
||||
// that exist on a form object.
|
||||
//
|
||||
//The other way to do it in a directive is to require "^form", but in a controller the only other way to do it
|
||||
// is to inject the $element object and use: $element.inheritedData('$formController');
|
||||
|
||||
var form = null;
|
||||
//var requiredFormProps = ["$error", "$name", "$dirty", "$pristine", "$valid", "$invalid", "$addControl", "$removeControl", "$setValidity", "$setDirty"];
|
||||
var requiredFormProps = ["$addControl", "$removeControl", "$setValidity", "$setDirty", "$setPristine"];
|
||||
|
||||
// a method to check that the collection of object prop names contains the property name expected
|
||||
function propertyExists(objectPropNames) {
|
||||
//ensure that every required property name exists on the current scope property
|
||||
return _.every(requiredFormProps, function (item) {
|
||||
|
||||
return _.contains(objectPropNames, item);
|
||||
});
|
||||
}
|
||||
|
||||
for (var p in scope) {
|
||||
|
||||
if (_.isObject(scope[p]) && p !== "this" && p.substr(0, 1) !== "$") {
|
||||
//get the keys of the property names for the current property
|
||||
var props = _.keys(scope[p]);
|
||||
//if the length isn't correct, try the next prop
|
||||
if (props.length < requiredFormProps.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//ensure that every required property name exists on the current scope property
|
||||
var containProperty = propertyExists(props);
|
||||
|
||||
if (containProperty) {
|
||||
form = scope[p];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return form;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name validateHasForm
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This will validate that the current scope has an assigned form object, if it doesn't an exception is thrown, if
|
||||
* it does we return the form object.
|
||||
*/
|
||||
getRequiredCurrentForm: function (scope) {
|
||||
var currentForm = this.getCurrentForm(scope);
|
||||
if (!currentForm || !currentForm.$name) {
|
||||
throw "The current scope requires a current form object (or ng-form) with a name assigned to it";
|
||||
}
|
||||
return currentForm;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name getNullForm
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns a null angular FormController, mostly for use in unit tests
|
||||
* NOTE: This is actually the same construct as angular uses internally for creating a null form but they don't expose
|
||||
* any of this publicly to us, so we need to create our own.
|
||||
*
|
||||
* @param {string} formName The form name to assign
|
||||
*/
|
||||
getNullForm: function (formName) {
|
||||
return {
|
||||
$addControl: angular.noop,
|
||||
$removeControl: angular.noop,
|
||||
$setValidity: angular.noop,
|
||||
$setDirty: angular.noop,
|
||||
$setPristine: angular.noop,
|
||||
$name: formName
|
||||
//NOTE: we don't include the 'properties', just the methods.
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('angularHelper', angularHelper);
|
||||
@@ -20,164 +20,6 @@ function legacyJsLoader(assetsService, umbRequestHelper) {
|
||||
}
|
||||
angular.module('umbraco.services').factory('legacyJsLoader', legacyJsLoader);
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Some angular helper/extension methods
|
||||
*/
|
||||
function angularHelper($log, $q) {
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.angularHelper#rejectedPromise
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* In some situations we need to return a promise as a rejection, normally based on invalid data. This
|
||||
* is a wrapper to do that so we can save one writing a bit of code.
|
||||
*
|
||||
* @param {object} objReject The object to send back with the promise rejection
|
||||
*/
|
||||
rejectedPromise: function (objReject) {
|
||||
var deferred = $q.defer();
|
||||
//return an error object including the error message for UI
|
||||
deferred.reject(objReject);
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name safeApply
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This checks if a digest/apply is already occuring, if not it will force an apply call
|
||||
*/
|
||||
safeApply: function (scope, fn) {
|
||||
if (scope.$$phase || scope.$root.$$phase) {
|
||||
if (angular.isFunction(fn)) {
|
||||
fn();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (angular.isFunction(fn)) {
|
||||
scope.$apply(fn);
|
||||
}
|
||||
else {
|
||||
scope.$apply();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name getCurrentForm
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns the current form object applied to the scope or null if one is not found
|
||||
*/
|
||||
getCurrentForm: function (scope) {
|
||||
|
||||
//NOTE: There isn't a way in angular to get a reference to the current form object since the form object
|
||||
// is just defined as a property of the scope when it is named but you'll always need to know the name which
|
||||
// isn't very convenient. If we want to watch for validation changes we need to get a form reference.
|
||||
// The way that we detect the form object is a bit hackerific in that we detect all of the required properties
|
||||
// that exist on a form object.
|
||||
//
|
||||
//The other way to do it in a directive is to require "^form", but in a controller the only other way to do it
|
||||
// is to inject the $element object and use: $element.inheritedData('$formController');
|
||||
|
||||
var form = null;
|
||||
//var requiredFormProps = ["$error", "$name", "$dirty", "$pristine", "$valid", "$invalid", "$addControl", "$removeControl", "$setValidity", "$setDirty"];
|
||||
var requiredFormProps = ["$addControl", "$removeControl", "$setValidity", "$setDirty", "$setPristine"];
|
||||
|
||||
// a method to check that the collection of object prop names contains the property name expected
|
||||
function propertyExists(objectPropNames) {
|
||||
//ensure that every required property name exists on the current scope property
|
||||
return _.every(requiredFormProps, function (item) {
|
||||
|
||||
return _.contains(objectPropNames, item);
|
||||
});
|
||||
}
|
||||
|
||||
for (var p in scope) {
|
||||
|
||||
if (_.isObject(scope[p]) && p !== "this" && p.substr(0, 1) !== "$") {
|
||||
//get the keys of the property names for the current property
|
||||
var props = _.keys(scope[p]);
|
||||
//if the length isn't correct, try the next prop
|
||||
if (props.length < requiredFormProps.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//ensure that every required property name exists on the current scope property
|
||||
var containProperty = propertyExists(props);
|
||||
|
||||
if (containProperty) {
|
||||
form = scope[p];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return form;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name validateHasForm
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This will validate that the current scope has an assigned form object, if it doesn't an exception is thrown, if
|
||||
* it does we return the form object.
|
||||
*/
|
||||
getRequiredCurrentForm: function(scope) {
|
||||
var currentForm = this.getCurrentForm(scope);
|
||||
if (!currentForm || !currentForm.$name) {
|
||||
throw "The current scope requires a current form object (or ng-form) with a name assigned to it";
|
||||
}
|
||||
return currentForm;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name getNullForm
|
||||
* @methodOf umbraco.services.angularHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns a null angular FormController, mostly for use in unit tests
|
||||
* NOTE: This is actually the same construct as angular uses internally for creating a null form but they don't expose
|
||||
* any of this publicly to us, so we need to create our own.
|
||||
*
|
||||
* @param {string} formName The form name to assign
|
||||
*/
|
||||
getNullForm: function(formName) {
|
||||
return {
|
||||
$addControl: angular.noop,
|
||||
$removeControl: angular.noop,
|
||||
$setValidity: angular.noop,
|
||||
$setDirty: angular.noop,
|
||||
$setPristine: angular.noop,
|
||||
$name: formName
|
||||
//NOTE: we don't include the 'properties', just the methods.
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('angularHelper', angularHelper);
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.umbPropertyEditorHelper
|
||||
@@ -198,19 +40,29 @@ function umbPropEditorHelper() {
|
||||
*/
|
||||
getViewPath: function (input, isPreValue) {
|
||||
var path = String(input);
|
||||
|
||||
if (path.startsWith('/')) {
|
||||
|
||||
//This is an absolute path, so just leave it
|
||||
return path;
|
||||
}
|
||||
else {
|
||||
var pathName = path.replace('.', '/');
|
||||
if (!isPreValue) {
|
||||
//i.e. views/propertyeditors/fileupload/fileupload.html
|
||||
return "views/propertyeditors/" + pathName + "/" + pathName + ".html";
|
||||
|
||||
if (path.indexOf("/") >= 0) {
|
||||
//This is a relative path, so just leave it
|
||||
return path;
|
||||
}
|
||||
else {
|
||||
//i.e. views/prevalueeditors/requiredfield.html
|
||||
return "views/prevalueeditors/" + pathName + ".html";
|
||||
if (!isPreValue) {
|
||||
//i.e. views/propertyeditors/fileupload/fileupload.html
|
||||
return "views/propertyeditors/" + path + "/" + path + ".html";
|
||||
}
|
||||
else {
|
||||
//i.e. views/prevalueeditors/requiredfield.html
|
||||
return "views/prevalueeditors/" + path + ".html";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -67,7 +67,7 @@ function DataTypeEditController($scope, $routeParams, $location, dataTypeResourc
|
||||
|
||||
$scope.$watch("content.selectedEditor", function (newVal, oldVal) {
|
||||
//when the value changes, we need to dynamically load in the new editor
|
||||
if (newVal && oldVal && newVal != oldVal) {
|
||||
if (newVal !== null && newVal !== undefined && newVal != oldVal) {
|
||||
//we are editing so get the content item from the server
|
||||
dataTypeResource.getPreValues(newVal)
|
||||
.then(function (data) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<div>
|
||||
Hello world
|
||||
</div>
|
||||
|
||||
@@ -5,10 +5,37 @@ using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using umbraco;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
[PropertyEditor(Constants.PropertyEditors.Date, "Date", "datepicker", ValueType = "DATE")]
|
||||
[PropertyEditor(Constants.PropertyEditors.DropDownList, "Dropdown list", "dropdown")]
|
||||
public class DropDownPropertyEditor : PropertyEditor
|
||||
{
|
||||
protected override PreValueEditor CreatePreValueEditor()
|
||||
{
|
||||
var editor = base.CreatePreValueEditor();
|
||||
|
||||
editor.Fields = new List<PreValueField>
|
||||
{
|
||||
new PreValueField
|
||||
{
|
||||
Description = "Add and remove values for the drop down list",
|
||||
//we're going to call this 'temp' because we are going to override the
|
||||
//serialization of the pre-values to ensure that each one gets saved with it's own key
|
||||
//(new db row per pre-value, thus to maintain backwards compatibility)
|
||||
Key = "temp",
|
||||
Name = ui.Text("editdatatype", "addPrevalue"),
|
||||
View = "Views/PropertyEditors/dropdown/dropdown.prevalue.html"
|
||||
}
|
||||
};
|
||||
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[PropertyEditor(Constants.PropertyEditors.Date, "Date", "DATE", "datepicker")]
|
||||
public class DatePropertyEditor : PropertyEditor
|
||||
{
|
||||
public DatePropertyEditor()
|
||||
|
||||
Reference in New Issue
Block a user