Skip to content

Instantly share code, notes, and snippets.

@vogucore
Last active August 24, 2019 16:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vogucore/efb0096e349591c235103e4f3f9e60d1 to your computer and use it in GitHub Desktop.
Save vogucore/efb0096e349591c235103e4f3f9e60d1 to your computer and use it in GitHub Desktop.
How to display fields of a content part when we add a new instance of a content type?
@inherits OrchardCore.DisplayManagement.Razor.RazorPage<TModel>
@using OrchardCore.DisplayManagement.Views
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, OrchardCore.DisplayManagement
using OrchardCore.Modules.Manifest;
[assembly: Module(
Name = "ExtB - Projects Module",
Author = "Demo Company",
Website = "http://democompany.com",
Version = "0.0.1",
Description = "Custom Module Workout",
Category = "Content Management"
)]
{
"ProjectPart": [
{
"place": "Content:1"
}
],
"TextField": [
{
"display-type": "Detail",
"differentiator": "ProjectPart-Description",
"place": "Content:2"
}
]
}
using System;
using OrchardCore.ContentFields.Fields;
using OrchardCore.ContentFields.Settings;
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.Data.Migration;
using ProjectModule.Indexes;
using ProjectModule.Models;
namespace ProjectModule.Migrations
{
public class ProjectMigration : DataMigration
{
private readonly IContentDefinitionManager _contentDefinitionManager;
public ProjectMigration(IContentDefinitionManager contentDefinitionManager)
{
_contentDefinitionManager = contentDefinitionManager;
}
public int Create()
{
_contentDefinitionManager.AlterTypeDefinition(
"Project",
builder => builder
.Creatable()
.Listable()
.WithPart(nameof(ProjectPart))
);
_contentDefinitionManager.AlterPartDefinition(nameof(ProjectPart),
builder => builder
.WithField(nameof(ProjectPart.Description),
field => field
.OfType(nameof(TextField))
.WithDisplayName("Description")
.Hint("Describe the project")
.WithDisplayMode("Detail")
.WithSetting("Editor", "TextArea")
)
);
SchemaBuilder.CreateMapIndexTable(nameof(ProjectPartIndex),
table => table
.Column<string>(nameof(ProjectPartIndex.ContentItemId), column => column.WithLength(26))
.Column<string>(nameof(ProjectPartIndex.Category))
.Column<DateTime?>(nameof(ProjectPartIndex.CreateDate))
);
return 1;
}
}
}
using System;
using OrchardCore.ContentFields.Fields;
using OrchardCore.ContentManagement;
using ProjectModule.Models.Enums;
namespace ProjectModule.Models
{
public class ProjectPart : ContentPart
{
public string Name { get; set; }
public string Category { get; set; }
public TextField Description { get; set; }
public ProjectType ProjectType { get; set; }
public DateTime? CreateDate { get; set; }
}
}
@model ShapeViewModel<ProjectModule.Models.ProjectPart>
<div><strong>@Model.Value.Name</strong></div>
<div>@T["Category: {0}", Model.Value.Category]</div>
<div>@T["Create Date: {0}", Model.Value.CreateDate?.ToShortDateString()]</div>
<div>@T["Project Type: {0}", Model.Value.ProjectType]</div>
@using ProjectModule.Models.Enums
@using ProjectModule.ViewModels
@model ProjectPartViewModel
<fieldset>
<label asp-for="Name">@T["Name"] <span asp-validation-for="Name"></span></label>
<input asp-for="Name" class="form-control" />
<span class="hint">@T["Project's name"]</span>
</fieldset>
<fieldset>
<label asp-for="ProjectType">@T["ProjectType"] <span asp-validation-for="ProjectType"></span></label>
<select asp-for="ProjectType" asp-items="Html.GetEnumSelectList<ProjectType>()" class="form-control"></select>
</fieldset>
<fieldset>
<label asp-for="Category">@T["Category"] <span asp-validation-for="Category"></span></label>
<input asp-for="Category" class="form-control" />
<span class="hint">@T["Project's Category"]</span>
</fieldset>
<fieldset class="form-group" asp-validation-class-for="CreateDate">
<label asp-for="CreateDate">@T["Project's Creation Date"] <span asp-validation-for="CreateDate"></span></label>
<input asp-for="CreateDate" type="date" class="form-control" />
</fieldset>
@model ShapeViewModel<ProjectModule.Models.ProjectPart>
@T["Project's name: {0}", Model.Value.Name]
using System.Collections.Generic;
using System.Threading.Tasks;
using OrchardCore.ContentManagement.Display.ContentDisplay;
using OrchardCore.ContentManagement.Display.Models;
using OrchardCore.ContentManagement.Metadata.Models;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.DisplayManagement.Views;
using ProjectModule.Models;
using ProjectModule.ViewModels;
namespace ProjectModule.Drivers
{
public class ProjectPartDisplayDriver : ContentPartDisplayDriver<ProjectPart>
{
//public override IDisplayResult Display(ProjectPart part) =>
// View(nameof(ProjectPart), part);
public override IDisplayResult Display(ProjectPart part, BuildPartDisplayContext context)
{
return View(nameof(ProjectPart), part);
}
public override IDisplayResult Edit(ProjectPart part)
{
return Initialize<ProjectPartViewModel>("ProjectPart_Edit", model =>
{
model.ProjectPart = part;
model.Name = part.Name;
model.Category = part.Category;
model.ProjectType = part.ProjectType;
model.CreateDate = part.CreateDate;
}).Location("Content: 1");
}
public override async Task<IDisplayResult> UpdateAsync(ProjectPart model, IUpdateModel updater)
{
var viewModel = new ProjectPartViewModel();
await updater.TryUpdateModelAsync(viewModel, Prefix);
model.Name = viewModel.Name;
model.Category = viewModel.Category;
model.ProjectType = viewModel.ProjectType;
model.CreateDate = viewModel.CreateDate;
return Edit(model);
}
}
}
using System;
using System.Collections.Generic;
using OrchardCore.ContentManagement;
using ProjectModule.Models;
using YesSql.Indexes;
namespace ProjectModule.Indexes
{
public class ProjectPartIndex : MapIndex
{
public string ContentItemId { get; set; }
public string Category { get; set; }
public DateTime? CreateDate { get; set; }
}
public class ProjectPartIndexProvider : IndexProvider<ContentItem>
{
public override void Describe(DescribeContext<ContentItem> context)
{
context.For<ProjectPartIndex>()
.Map(contentItem =>
{
var projectPart = contentItem.As<ProjectPart>();
if (projectPart != null)
{
return new ProjectPartIndex
{
ContentItemId = contentItem.ContentItemId,
Category = projectPart.Category,
CreateDate = projectPart.CreateDate
};
}
return null;
});
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using OrchardCore.Modules;
using ProjectModule.Models;
using ProjectModule.Models.Enums;
namespace ProjectModule.ViewModels
{
public class ProjectPartViewModel : IValidatableObject
{
[Required] public string Name { get; set; }
[Required] public ProjectType ProjectType { get; set; }
public string Category { get; set; }
public DateTime? CreateDate { get; set; }
[BindNever] public ProjectPart ProjectPart { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var T = validationContext.GetService<IStringLocalizer<ProjectPartViewModel>>();
var clock = validationContext.GetService<IClock>();
if (CreateDate.HasValue)
{
if (CreateDate.Value > clock.UtcNow)
{
yield return new ValidationResult(T["Creation date cannot be bigger than today's date."], new[] { nameof(CreateDate) });
}
}
}
}
}
namespace ProjectModule.Models.Enums
{
public enum ProjectType
{
Scrum,
Kanban
}
}
using System;
using Fluid;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.ContentManagement;
using OrchardCore.ContentManagement.Display.ContentDisplay;
using OrchardCore.Data.Migration;
using OrchardCore.Modules;
using ProjectModule.Drivers;
using ProjectModule.Indexes;
using ProjectModule.Migrations;
using ProjectModule.Models;
using ProjectModule.ViewModels;
using YesSql.Indexes;
namespace ProjectModule
{
public class Startup : StartupBase
{
static Startup()
{
TemplateContext.GlobalMemberAccessStrategy.Register<ProjectPartViewModel>();
}
public override void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ContentPart, ProjectPart>();
services.AddScoped<IDataMigration, ProjectMigration>();
services.AddSingleton<IIndexProvider, ProjectPartIndexProvider>();
services.AddScoped<IContentPartDisplayDriver, ProjectPartDisplayDriver>();
}
public override void Configure(IApplicationBuilder builder, IRouteBuilder routes, IServiceProvider serviceProvider)
{
routes.MapAreaRoute(
name: "ExtBProject-Home",
areaName: "ProjectModule",
template: "Project/{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment