Fixed a binding issue with FormsElementDriver.

This fixes the issue where form elements whose drivers inherit from FormsElementDriver would not persist their changes.

Fixes #6100, #6035
This commit is contained in:
Sipke Schoorstra
2015-12-03 22:47:15 +01:00
parent 37bbafede6
commit 8693b68ac7
26 changed files with 129 additions and 50 deletions

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -11,7 +11,7 @@ namespace Orchard.DynamicForms.Drivers {
public class ButtonElementDriver : FormsElementDriver<Button> {
private readonly ITokenizer _tokenizer;
public ButtonElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public ButtonElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -1,8 +1,8 @@
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -10,8 +10,8 @@ namespace Orchard.DynamicForms.Drivers {
public class CheckboxElementDriver : FormsElementDriver<CheckBox> {
private readonly ITokenizer _tokenizer;
public CheckboxElementDriver(IFormManager formManager, ITokenizer tokenizer)
: base(formManager) {
public CheckboxElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer)
: base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -4,11 +4,12 @@ using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Services;
namespace Orchard.DynamicForms.Drivers {
public class CommonFormElementDriver : FormsElementDriver<FormElement> {
public CommonFormElementDriver(IFormManager formManager, IShapeFactory shapeFactory) : base(formManager) {
public CommonFormElementDriver(IFormsBasedElementServices formsServices, IShapeFactory shapeFactory) : base(formsServices) {
New = shapeFactory;
}

View File

@@ -1,8 +1,8 @@
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -10,7 +10,7 @@ namespace Orchard.DynamicForms.Drivers {
public class EmailFieldElementDriver : FormsElementDriver<EmailField>{
private readonly ITokenizer _tokenizer;
public EmailFieldElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public EmailFieldElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -3,18 +3,18 @@ using System.Linq;
using System.Web.Mvc;
using Orchard.DynamicForms.Elements;
using Orchard.DynamicForms.Helpers;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
namespace Orchard.DynamicForms.Drivers {
public class EnumerationElementDriver : FormsElementDriver<Enumeration> {
private readonly ITokenizer _tokenizer;
public EnumerationElementDriver(IFormManager formManager, ITokenizer tokenizer)
: base(formManager) {
public EnumerationElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer)
: base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -7,7 +7,6 @@ using Orchard.ContentManagement.MetaData.Models;
using Orchard.DynamicForms.Elements;
using Orchard.DynamicForms.Helpers;
using Orchard.DynamicForms.Services;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
@@ -24,14 +23,14 @@ namespace Orchard.DynamicForms.Drivers {
private readonly ITokenizer _tokenizer;
public FormElementDriver(
IFormManager formManager,
IFormsBasedElementServices formsServices,
IContentDefinitionManager contentDefinitionManager,
IFormService formService,
ICurrentControllerAccessor currentControllerAccessor,
ICultureAccessor cultureAccessor,
ITokenizer tokenizer)
: base(formManager) {
: base(formsServices) {
_contentDefinitionManager = contentDefinitionManager;
_formService = formService;
_currentControllerAccessor = currentControllerAccessor;

View File

@@ -1,16 +1,16 @@
using System.Collections.Generic;
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
namespace Orchard.DynamicForms.Drivers {
public class HiddenFieldElementDriver : FormsElementDriver<HiddenField> {
private readonly ITokenizer _tokenizer;
public HiddenFieldElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public HiddenFieldElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -11,7 +11,7 @@ namespace Orchard.DynamicForms.Drivers {
public class LabelElementDriver : FormsElementDriver<Label> {
private readonly ITokenizer _tokenizer;
public LabelElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public LabelElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -1,8 +1,8 @@
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -10,7 +10,7 @@ namespace Orchard.DynamicForms.Drivers {
public class PasswordFieldElementDriver : FormsElementDriver<PasswordField>{
private readonly ITokenizer _tokenizer;
public PasswordFieldElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public PasswordFieldElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -6,16 +6,14 @@ using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.Core.Title.Models;
using Orchard.DynamicForms.Elements;
using Orchard.DynamicForms.Helpers;
using Orchard.Environment.Extensions;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Projections.Models;
using Orchard.Projections.Services;
using Orchard.Tokens;
using Orchard.Utility.Extensions;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
namespace Orchard.DynamicForms.Drivers {
@@ -25,8 +23,8 @@ namespace Orchard.DynamicForms.Drivers {
private readonly IContentManager _contentManager;
private readonly ITokenizer _tokenizer;
public QueryElementDriver(IFormManager formManager, IProjectionManager projectionManager, IContentManager contentManager, ITokenizer tokenizer)
: base(formManager) {
public QueryElementDriver(IFormsBasedElementServices formsServices, IProjectionManager projectionManager, IContentManager contentManager, ITokenizer tokenizer)
: base(formsServices) {
_projectionManager = projectionManager;
_contentManager = contentManager;
_tokenizer = tokenizer;

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -11,8 +11,8 @@ namespace Orchard.DynamicForms.Drivers {
public class RadioButtonElementDriver : FormsElementDriver<RadioButton> {
private readonly ITokenizer _tokenizer;
public RadioButtonElementDriver(IFormManager formManager, ITokenizer tokenizer)
: base(formManager) {
public RadioButtonElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer)
: base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -2,10 +2,10 @@
using Orchard.ContentManagement;
using Orchard.DynamicForms.Elements;
using Orchard.Environment.Extensions;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -15,7 +15,7 @@ namespace Orchard.DynamicForms.Drivers {
private readonly IOrchardServices _services;
private readonly ITokenizer _tokenizer;
public ReCaptchaElementDriver(IFormManager formManager, IOrchardServices services, ITokenizer tokenizer) : base(formManager) {
public ReCaptchaElementDriver(IFormsBasedElementServices formsServices, IOrchardServices services, ITokenizer tokenizer) : base(formsServices) {
_services = services;
_tokenizer = tokenizer;
}

View File

@@ -5,10 +5,10 @@ using System.Linq;
using System.Web.Mvc;
using Orchard.DynamicForms.Elements;
using Orchard.Environment.Extensions;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Taxonomies.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -19,8 +19,8 @@ namespace Orchard.DynamicForms.Drivers {
private readonly ITaxonomyService _taxonomyService;
private readonly ITokenizer _tokenizer;
public TaxonomyElementDriver(IFormManager formManager, ITaxonomyService taxonomyService, ITokenizer tokenizer)
: base(formManager) {
public TaxonomyElementDriver(IFormsBasedElementServices formsServices, ITaxonomyService taxonomyService, ITokenizer tokenizer)
: base(formsServices) {
_taxonomyService = taxonomyService;
_tokenizer = tokenizer;
}

View File

@@ -1,16 +1,15 @@
using System.Collections.Generic;
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.DynamicForms.Elements;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
namespace Orchard.DynamicForms.Drivers {
public class TextAreaElementDriver : FormsElementDriver<TextArea> {
private readonly ITokenizer _tokenizer;
public TextAreaElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public TextAreaElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -1,8 +1,8 @@
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -10,7 +10,7 @@ namespace Orchard.DynamicForms.Drivers {
public class TextFieldElementDriver : FormsElementDriver<TextField>{
private readonly ITokenizer _tokenizer;
public TextFieldElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public TextFieldElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -1,8 +1,8 @@
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -10,7 +10,7 @@ namespace Orchard.DynamicForms.Drivers {
public class UrlFieldElementDriver : FormsElementDriver<UrlField> {
private readonly ITokenizer _tokenizer;
public UrlFieldElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public UrlFieldElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using Orchard.DynamicForms.Elements;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using Orchard.Tokens;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
@@ -11,7 +11,7 @@ namespace Orchard.DynamicForms.Drivers {
public class ValidationMessageElementDriver : FormsElementDriver<ValidationMessage> {
private readonly ITokenizer _tokenizer;
public ValidationMessageElementDriver(IFormManager formManager, ITokenizer tokenizer) : base(formManager) {
public ValidationMessageElementDriver(IFormsBasedElementServices formsServices, ITokenizer tokenizer) : base(formsServices) {
_tokenizer = tokenizer;
}

View File

@@ -199,7 +199,9 @@
<Compile Include="Handlers\WorkflowValidatorCoordinator.cs" />
<Compile Include="ResourceManifest.cs" />
<Compile Include="Services\FieldsetModelMap.cs" />
<Compile Include="Services\FormElementServices.cs" />
<Compile Include="Services\FormModelMap.cs" />
<Compile Include="Services\IFormElementServices.cs" />
<Compile Include="Services\Models\FormSubmissionTokenContext.cs" />
<Compile Include="Handlers\ValidatorsCoordinator.cs" />
<Compile Include="Handlers\FormSubmissionCoordinator.cs" />

View File

@@ -0,0 +1,14 @@
using Orchard.Forms.Services;
using Orchard.Localization.Services;
namespace Orchard.DynamicForms.Services {
public class FormElementServices : IFormElementServices {
public FormElementServices(IFormManager formManager, ICultureManager cultureManager) {
FormManager = formManager;
CultureManager = cultureManager;
}
public IFormManager FormManager { get; private set; }
public ICultureManager CultureManager { get; private set; }
}
}

View File

@@ -0,0 +1,10 @@
using Orchard.Forms.Services;
using Orchard.Localization.Services;
namespace Orchard.DynamicForms.Services {
public interface IFormElementServices : IDependency
{
IFormManager FormManager { get; }
ICultureManager CultureManager { get; }
}
}

View File

@@ -19,6 +19,7 @@ using Orchard.Projections.ViewModels;
using Orchard.Tokens;
using Orchard.UI.Navigation;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
using DescribeContext = Orchard.Forms.Services.DescribeContext;
namespace Orchard.Layouts.Drivers {
@@ -32,13 +33,13 @@ namespace Orchard.Layouts.Drivers {
private readonly IDisplayHelperFactory _displayHelperFactory;
public ProjectionElementDriver(
IFormManager formManager,
IFormsBasedElementServices formsServices,
IProjectionManager projectionManager,
IOrchardServices services,
IRepository<LayoutRecord> layoutRepository,
ITokenizer tokenizer,
IDisplayHelperFactory displayHelperFactory)
: base(formManager) {
: base(formsServices) {
_projectionManager = projectionManager;
_contentManager = services.ContentManager;

View File

@@ -5,13 +5,14 @@ using Orchard.Forms.Services;
using Orchard.Layouts.Elements;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.Services;
namespace Orchard.Layouts.Drivers {
public class ShapeElementDriver : FormsElementDriver<Shape> {
private readonly IShapeFactory _shapeFactory;
public ShapeElementDriver(IFormManager formManager, IShapeFactory shapeFactory)
: base(formManager) {
public ShapeElementDriver(IFormsBasedElementServices formsServices, IShapeFactory shapeFactory)
: base(formsServices) {
_shapeFactory = shapeFactory;
}

View File

@@ -3,13 +3,17 @@ using System.Collections.Generic;
using System.Linq;
using Orchard.Forms.Services;
using Orchard.Layouts.Framework.Elements;
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Services;
namespace Orchard.Layouts.Framework.Drivers {
public abstract class FormsElementDriver<TElement> : ElementDriver<TElement>, IFormProvider where TElement : Element {
private readonly IFormManager _formManager;
private readonly ICultureAccessor _cultureAccessor;
protected FormsElementDriver(IFormManager formManager) {
_formManager = formManager;
protected FormsElementDriver(IFormsBasedElementServices formsServices) {
_formManager = formsServices.FormManager;
_cultureAccessor = formsServices.CultureAccessor;
}
protected dynamic BuildForm(ElementEditorContext context, string formName, string position = null) {
@@ -34,11 +38,37 @@ namespace Orchard.Layouts.Framework.Drivers {
protected dynamic BuildForms(ElementEditorContext context) {
// TODO: Fix Forms API so that it works with prefixes. Right now only binding implements prefix, but building a form ignores the specified prefix.
var forms = FormNames.Reverse().Select(x => _formManager.Bind(_formManager.Build(x), context.ValueProvider)).ToArray();
// If not a post-back, we need to bind the form with the element's data values. Otherwise, bind the form with the posted values.
var valueProvider = context.Updater == null
? context.Element.Data.ToValueProvider(_cultureAccessor.CurrentCulture)
: context.ValueProvider;
var forms = FormNames.Reverse().Select(x => {
var shape = _formManager.Bind(_formManager.Build(x), valueProvider);
if (context.Updater != null) {
// Update the element's data dictionary with the posted values.
Action<object> process = s => UpdateElementProperty(s, context);
FormNodesProcessor.ProcessForm(shape, process);
}
return shape;
}).ToArray();
var formShape = context.ShapeFactory.ElementEditor__Forms(Forms: forms);
return formShape;
}
private void UpdateElementProperty(dynamic formElementShape, ElementEditorContext context) {
var name = (string)formElementShape.Name;
if (name != null) {
var value = context.ValueProvider.GetValue(context.Prefix + name);
if (value != null) {
context.Element.Data[name] = value.AttemptedValue;
}
}
}
public void Describe(DescribeContext context) {
DescribeForm(context);
}

View File

@@ -330,12 +330,14 @@
<Compile Include="Helpers\SnippetHtmlExtensions.cs" />
<Compile Include="Helpers\StringHelper.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Services\FormElementServices.cs" />
<Compile Include="Services\ICurrentThemeShapeBindingResolver.cs" />
<Compile Include="Services\CurrentThemeShapeBindingResolver.cs" />
<Compile Include="Providers\PlaceableContentElementHarvester.cs" />
<Compile Include="Elements\RecycleBin.cs" />
<Compile Include="Models\SnippetDescriptor.cs" />
<Compile Include="Models\SnippetFieldDescriptor.cs" />
<Compile Include="Services\IFormElementServices.cs" />
<Compile Include="ViewModels\SnippetViewModel.cs" />
<Compile Include="ViewModels\SnippetFieldViewModel.cs" />
<Compile Include="ViewModels\PlaceableContentItemViewModel.cs" />

View File

@@ -0,0 +1,13 @@
using Orchard.Forms.Services;
namespace Orchard.Layouts.Services {
public class FormsBasedElementServices : IFormsBasedElementServices {
public FormsBasedElementServices(IFormManager formManager, ICultureAccessor cultureAccessor) {
FormManager = formManager;
CultureAccessor = cultureAccessor;
}
public IFormManager FormManager { get; private set; }
public ICultureAccessor CultureAccessor { get; private set; }
}
}

View File

@@ -0,0 +1,9 @@
using Orchard.Forms.Services;
namespace Orchard.Layouts.Services {
public interface IFormsBasedElementServices : IDependency
{
IFormManager FormManager { get; }
ICultureAccessor CultureAccessor { get; }
}
}