I have used html.ValidationSummary to get all errors displayed on top of the page.
This will render list with errors on top of the page.
Example:
<ul>
<li>UserName is invalid</li>
</ul>
I have how ever need to render every item instead of list as custom div with additional html tags inside.
I need every line to be rendered as short example below (this is only one line):
<div>
<div class="right"><a href="#closeError">Close error</div>
<div class="right"><a href="#Update">Update Field</div>
<label>Error:</label> Name on the page is invalid.
</div>
What is your opininon how to achieve this rendering?
I have considered to create html helper where i will take ModelState and get all errors, but not sure this will work...
I have considered to create html helper where i will take ModelState and get all errors, but not sure this will work...
Why wouldn't that work?
public static class ValidationExtensions
{
public static IHtmlString MyValidationSummary(this HtmlHelper htmlHelper)
{
var formContext = htmlHelper.ViewContext.ClientValidationEnabled
? htmlHelper.ViewContext.FormContext
: null;
if (formContext == null && htmlHelper.ViewData.ModelState.IsValid)
{
return null;
}
var sb = new StringBuilder();
var htmlSummary = new TagBuilder("div");
var modelStates = htmlHelper.ViewData.ModelState.Values;
sb.AppendLine("<div class=\"right\"><a href=\"#closeError\">Close error</div>");
sb.AppendLine("<div class=\"right\"><a href=\"#Update\">Update Field</div>");
if (modelStates != null)
{
foreach (ModelState modelState in modelStates)
{
foreach (ModelError modelError in modelState.Errors)
{
var userErrorMessageOrDefault = GetUserErrorMessageOrDefault(modelError);
if (!string.IsNullOrEmpty(userErrorMessageOrDefault))
{
sb.AppendFormat("<label>Error:</label> {0}{1}", htmlHelper.Encode(userErrorMessageOrDefault), Environment.NewLine);
}
}
}
}
htmlSummary.InnerHtml = sb.ToString();
if (formContext != null)
{
formContext.ReplaceValidationSummary = true;
}
return MvcHtmlString.Create(htmlSummary.ToString(TagRenderMode.Normal));
}
private static string GetUserErrorMessageOrDefault(ModelError error)
{
if (!string.IsNullOrEmpty(error.ErrorMessage))
{
return error.ErrorMessage;
}
return null;
}
}
and then:
<%= Html.MyValidationSummary() %>
Related
I can't seem to figure out the right way to get the target object. Here is the code front end code that is supposed to have drag and drop functionality:
<div class="pos-top">
<div id="imgGrid" class="grid bg-white" style="grid-template-columns:repeat(#columnCount, #(unitWidth)); grid-auto-flow:dense;">
#foreach (var b in blocks)
{
#if ((b.Placement[_pageType].Visible == true || showHiddenBlocks == true) && b.Zones != null && b.Zones.Contains(zone))
{
var id = b.Id;
<div class="col-span-#b.ColSpan row-span-#b.RowSpan relative border border-black box-border #(b.isDragOver?"dropped":"")" style=" order:#b.Placement[_pageType].Order;" #ondblclick="(() => ChangeBlockProperties(b))"
draggable="true"
data-block-id="#b.Id"
id="#id" #ondrop="#((e) => ondropOver(b, blocks.ToList()))"
ondragover="event.preventDefault();"
#ondragstart="#((e) => ondragstart(e, b, blocks.ToList()))"
#ondragenter="#(() => ondragenter(b))"
#ondragleave="#(() => { b.isDragOver = false; })"
#ondragend="#(() => ondragend(b, blocks.ToList()))">
<div class="blockNumberInfo absolute rounded-full bg-red-700 flex justify-center items-center border-2 border-black"
style="width:40px;height:20px">
#b.LocalIndex / #b.Placement[_pageType].Order
</div>
</div>
}
}
</div>
}
}
</div>
This is my code that is moving the blocks around:
public async void ondropOver(FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
DragEnter = null;
if (DraggedItem == null) return;
if (DraggedItem == item) return;
DraggedItem.Placement[_pageType].Order = item.Placement[_pageType].Order;
await BlockplacementEditService.SaveBlockChangesAsync(flyerBlocks, DraggedItem, DraggedItem.Placement[_pageType].Order, _pageType, zone);
DraggedItem = null;
item.isDragOver = false;
//StateHasChanged();
}
public void ondragstart(DragEventArgs e, FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
e.DataTransfer.EffectAllowed = "move";
DraggedItem = item;
DraggedItemPosition = item.Placement[_pageType].Order;
}
public void ondragenter(FlyerBlock item)
{
item.isDragOver = true;
DragEnter = item;
}
public async void ondragend(FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
item.isDragOver = false;
if (DraggedItem == null) return;
DragEnter = null;
// item.isDragOver = true;
}
The issue I am running into is that I dont know how to pass the targetblock into my drop over event. I tried using DragEventArgs but that does not work I have also tried using jsruntime but I can only extract the dragged block. I want to be able to get the target block so I can update the order correctly. Any help would be appreciated!
I have a requirement to create breadcrumb in sightly. I have following code which is working fine in JSP. But i am struggling to convert the code to sightly because i am not getting the right methods in currentStyle object to get the "absParent" and others. Any help will be highly appreciated!!
<%# include file="/libs/foundation/global.jsp" %>
<%
final int startLevel = currentStyle.get("absParent", 3);
final int endLevel = currentPage.getDepth() - currentStyle.get("relParent", 0);
final int minItems = currentStyle.get("minItems", 2);
if (startLevel <= endLevel - minItems) {
%><section class="breadcrumbs"><%
for (int level = startLevel+1; level < endLevel; ++level) {
Page itemPage = currentPage.getAbsoluteParent(level);
if (itemPage == null || !itemPage.isValid() || itemPage.isHideInNav()) {
continue;
}
final String pagePath = itemPage.getPath() + ".html";
final String pageTitle = itemPage.getNavigationTitle();
String className = "breadcrumb-item-"+level;
if (level == startLevel) className += " breadcrumb-first";
if (level == endLevel-1) className += " breadcrumb-last";
pageContext.setAttribute("className", className);%>
<section class="breadcrumbs ">
<%= xssAPI.encodeForHTML(pageTitle) %>
</section>
<%} %>
</section><%
}
%>
To create breadcrumb you have to write a WCMuse class and include that in this component.
<div
data-sly-use.breadcrumb="${'com.mySite.components.BreadcrumbUse'}">
<!-- + Breadcrumb component + -->
<div class="breadcrumb component">
<div class="breadcrumb_nav_bar clearfix"
data-sly-test="${breadcrumb.navList}"
data-sly-list.element="${breadcrumb.navList}">
<p data-sly-test="${!elementList.last}">
<a href="${element.path}.html">${element.title ||
element.navigationTitle || element.name}</a>
</p>
<p data-sly-test="${elementList.last}">${element.title ||
element.navigationTitle || element.name}</p>
</div>
</div>
<!-- - Breadcrumb component - -->
</div>
Code Sample for WCMUse class:
Public class BreadcrumbUse extends WCMUse
{
private List<Page> navList = new ArrayList<Page>();
#Override
public void activate() throws Exception
{
setBreadCrumbItems();
}
private void setBreadCrumbItems()
{
long level = 4L;
long endLevel = 1L;
int currentLevel = getCurrentPage().getDepth();
while (level < currentLevel - endLevel)
{
Page trailPage = getCurrentPage().getAbsoluteParent((int) level);
if (trailPage == null)
{
break;
}
this.navList.add(trailPage);
level++;
}
}
public List<Page> getNavList()
{
return this.navList;
}
}
The below code will work for creating breadcrumbs in AEM6.2 using Javascript and HTL(previously sightly).It worked well for me..here we go
Javascript to be used in the server side script(it can also be created using java)
script.js
use(function () {
var title = currentPage.getTitle();
//To get the title of the current page
var level = currentPage.getDepth();
//To find the depth of the current page from the root
var cts = new Array();
// To store the traversed page (object) from the root
for(var i=1;i<level;i++)
{ // Here I used i=1 for mycase(i=0 will be /content)
var titl = currentPage.getAbsoluteParent(i);
//To get the absolute parent at each level from root
pageStack.push(titl);
//Stack to maintain the pages
}
return {
title: title,
pageStack:pageStack
};
});
Breadcrumbs.html
<sly data-sly-use.cpt="script.js">
<h1>${cpt.title}</h1>
<div data-sly-list="${cpt.pageStack}">
<span> ${item.title}/</span>
</div>
</div>
Thus we get the breadcrumbs ready for our presentation!!!
What is the best practice for this:
I have a list of partials on one page. Each page has a form on it to save the data of the partial.
I do this like this on the main page:
#foreach (var taak in Model)
{
#Html.Action("DetailTaak", "Checklist", new { trouwTaakId = taak.Id })
}
Then the controller is this (where the data is filled):
public ActionResult DetailTaak(int trouwTaakId)
{
DTO.Trouw.TrouwTaak viewModel;
viewModel = _themaService.GetTrouwTaakByTrouwTaakId(trouwTaakId);
return View(viewModel);
}
The page gets build and the list is completed. Now when I want to save a partial using this code:
#using (Html.BeginForm("DetailTaak", "Checklist", FormMethod.Post, new { #class = "form-horizontal col-md-12", role = "form", id = #Model.Id }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
...
}
It works but what do I do so the mainpage doesn't have to be reloaded ? This is the post code:
[HttpPost]
public ActionResult DetailTaak(DTO.Trouw.TrouwTaak model)
{
if (ModelState.IsValid)
{
ViewBag.SaveSuccess = "Je instellingen zijn opgeslagen";
}
return View("DetailTaak", model);
}
With this post code I go to the DetailTaak page instead of staying on the main page and just updating the partial.
I am doing something wrong but I don't know which way to go.
kind regards
I'm migrating wicket from 1.3.6 to 1.4.0. I get syntax error by getModel() and getModelObject() methods. It says they are undefined, so they prevent application from compiling. Which methods should I use instead of them?
This is part of my code:
#SuppressWarnings("unchecked")
public BreadCrumbTrail(String id, IModel model) {
super(id, model);
// Keep a count of the crumbs
int count = 1;
// Get the crumbs
List<Crumb> crumbs = (List<Crumb>) getModelObject();
// Create a repeating view to render the crumbs within
RepeatingView repeating = new RepeatingView("crumbs");
add(repeating);
// Add each crumb
for (final Crumb crumb : crumbs) {
WebMarkupContainer item = new WebMarkupContainer(repeating
.newChildId());
repeating.add(item);
// Create a link from the page held in the crumb
#SuppressWarnings("serial")
Link link = new Link("link", item.getModel()) {
public void onClick() {
setResponsePage(crumb.getPage());
}
};
// Add a title/label to the link
link.add(new Label("title", crumb.getTitle()));
item.add(link);
// Is this the last crumb?
if (count == crumbs.size()) {
// Don't add the normal separator
item.add(new Label("separator", " "));
// Disable the link as this is the current page
link.setEnabled(false);
} else {
// Add the separator
item.add(new Label("separator", " > "));
}
// Up the count of crumbs
count++;
}
}
use getDefaultModelObject() instead
Wicket usually provides a migration guide:
https://cwiki.apache.org/WICKET/migrating-to-wicket-14.html#MigratingtoWicket1.4-Component.getModel%2528%2529andfriendsrenamedtogetDefaultModel%2528%2529andfriends
BTW: wicket 1.5 is also already out
In my ASP.NET MVC 2 application I use HandleErrorAttribute to display a custom error page in case of unhandled exceptions, and it works perfectly unless the exception happens in an action called by Ajax.ActionLink. In this case nothing happens. Is it possible to use HandleErrorAttribute to update the target element with the contents of an "Error.ascx" partial view?
To achieve this you could write a custom action filter:
public class AjaxAwareHandleErrorAttribute : HandleErrorAttribute
{
public string PartialViewName { get; set; }
public override void OnException(ExceptionContext filterContext)
{
// Execute the normal exception handling routine
base.OnException(filterContext);
// Verify if AJAX request
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
// Use partial view in case of AJAX request
var result = new PartialViewResult();
result.ViewName = PartialViewName;
filterContext.Result = result;
}
}
}
And then specify the partial view to be used:
[AjaxAwareHandleError(PartialViewName = "~/views/shared/error.ascx")]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult SomeAction()
{
throw new Exception("shouldn't have called me");
}
}
And finally in your view assuming you have the following link:
<%= Ajax.ActionLink("some text", "someAction", new AjaxOptions {
UpdateTargetId = "result", OnFailure = "handleFailure" }) %>
You could make the handleFailure function to update the proper div:
<script type="text/javascript">
function handleFailure(xhr) {
// get the error text returned by the partial
var error = xhr.get_response().get_responseData();
// place the error text somewhere in the DOM
document.getElementById('error').innerHTML = error;
}
</script>