Is it possible to pass object as parameters in a web user control markup? - webforms

I am building a web page that lists products, using aspx webform. For that, in a user control corresponding to my list, I am looping over my products and injecting one new user control by product:
foreach (Product p in this.Products)
{
ucProductItem.product = p;
%>
<uc:ucProductItem runat="server" ID="ucProductItem" />
<%
}
%>
This works fine and I am OK with that... BUT not totally because I find this quite ugly and messy; I don't like the mixing of markup and code in the template, and I try to use markup as much as possible (and I have this problem all over my project).
Thus, I would like to pass the product p to the new ucProductItem user control via the markup, and I tried naturaly something like:
<uc:ucProductItem runat="server" ID="ucProductItem" product=p />
I know this is possible for primitive types such as strings and integers, but I can not figure out how to do it with objects.
Is that possible ? And how ?

Related

Can not input to EditableElement of CKEditor5

In CKEditor5, I tried implementing custom element to convert model to view for editing. Then, editable element(#ckeditor/ckeditor5-engine/src/view/editableelement) in container element(#ckeditor/ckeditor5-engine/src/view/containerelement) is focused on the parent container element and can not be edited.
For example, if it is implemented as follows:
buildModelConverter().for(editing.modelToView)
.fromElement('myElement')
.toElement(new ContainerElement('div', {}, [new EditableElement('h4')]));
The result of actual editing dom after inserting 'myElement' and keydown "abc". (I hope inputting text of "abc" to h4 tag but...)
<div>​​​​​​​
abc
<h4>
<br data-cke-filler="true">
</h4>
</div>
I also tried using widget for applying contenteditable attribute.
But, text couldn't be entered in h4.
<div class="ck-widget" contenteditable="false">​​​​​​​
<h4 class="ck-editable" contenteditable="true">
<br data-cke-filler="true">
</h4>
</div>
Is this bug, or I made mistake understanding of container element?
[Additional details]
I am assuming to make a widget plugin for ranking list.
First, the ranking list is structured by <ol> and <li> tags because of having multiple items.
I solved that by defining two schema such as "rankingList" and "rankingListItem",
so I realized dynamic elements using nested model elements.
const item1 = new ModelElement('rankingListItem');
const item2 = new ModelElement('rankingListItem');
const model = new ModelElement('rankingList', {}, [item1, item2]);
// and insert
Next, the item of ranking list has link, image, title and note.
Therefore, the ranking list item has the following DOM structure:
<ol><!-- apply toWidget -->
<li>
<a href="link[editable]">
<img src="image[editable]">
<h3>title[editable]</h3>
<p>notes[editable]</p>
</a>
</li>
...
</ol>
I expect the view element is the following:
const {ref, src, title, notes} = data; // how to get data?
const view = new ContainerElement('a', {ref}, [
new EmptyElement('img', {src}),
new EditableElement('h3', {}, new Text(title)),
new EditableElement('p', {}, new Text(title)),
]);
// maybe incorrect ...
In conclusion, I want to use editable view not to break defined DOM tree.
How can I realize it?
Thank you for describing your case. It means a lot for us at the moment to know how developers are using the editor and what are your expectations.
Unfortunately, this looks like a very complex feature. It also looks like it would need custom UI (to edit link url and image src -- unless they do not change after added to the editor). It seems that you struggle with two problems:
position mapping between the model and the view,
nested editables.
First, to answer your question about EditableElement - it seems to be correct to use them for h3 and p elements.
However, such complex feature needs custom converters. Converter builders (which you used) are dedicated to being used in simple cases, like element-to-element conversion, or attribute-to-attribute conversion.
Behind the nice API, build converter is a function factory, that creates one or multiple functions. Those are then added as callbacks to ModelConversionDispatcher (which editor.editing.modelToView is an instance of). ModelConversionDispatcher fires a series of events during the conversion, which is a process of translating a change in the model to the view.
As I've mentioned, you would have to write those converting functions by yourself.
Since this is too big of a subject for a detailed and thorough answer, I'll just briefly present you what you should be interested in. Unfortunately, there are no guides yet about creating custom converters from scratch. This is a very broad subject.
First, let me explain you from where most of your problems come from. As you already know, the editor has three layers: model (data), view (DOM-like structure) and DOM. Model is converted to view and view is rendered to DOM. Also, the other way, when you load data, DOM is converted to view and view is converted to model. This is why you need to provide model-to-view converter and view-to-model converter for your feature.
The important piece of this puzzle is engine.conversion.Mapper. Its role is to map elements and positions from model to view. As you already might have seen, the model might be quite different than the view. Correct position mapping between those is key. When you type a letter at caret position (in DOM), this position is mapped to model and the letter is inserted in the model and only then converted back to the view and DOM. If view-to-model position conversion is wrong, you will not be able to type, or really do anything, at that place.
Mapper is pretty simple on its own. All it needs is that you specify which view elements are bound to which model elements. For example, in the model you might have:
<listItem type="bulleted" indent="0">Foo</listItem>
<listItem type="bulleted" indent="1">Bar</listItem>
While in the view you have:
<ul>
<li>
Foo
<ul>
<li>Bar</li>
</ul>
</li>
</ul>
If the mapper knows that first listItem is bound with first <li> and the second listItem is bound with second <li>, then it is able to translate positions correctly.
Back to your case. Each converter has to provide data for Mapper. Since you used converter builder, the converters build by it already do this. But they are simple, so when you provide:
buildModelConverter().for(editing.modelToView)
.fromElement('myElement')
.toElement(new ContainerElement('div', {}, [new EditableElement('h4')]));
it is assumed, that myElement is bound with the <div>. So anything that is written inside that <div> will go straight to myElement and then will be rendered at the beginning of myElement:
<div>
<h4></h4>
</div>
Assuming that you just wrote x at <h4>, that position will be mapped to myElement offset 0 in the model and then rendered to view at the beginning of <div>.
Model:
<myElement>x</myElement>
View:
<div>x<h4></h4></div>
As you can see, in your case, it is <h4> which should be bound with myElement.
At the moment, we are during refactoring phase. One of the goals is providing more utility functions for converter builders. One of those utilities are converters for elements which have a wrapper element, like in that "div + h4" case above. This is also a case of image feature. The image is represented by <image> in model but it is <figure><img /></figure> in the view. You can look at ckeditor5-image to see how those converters look like now. We want to simplify them.
Unfortunately, your real case is even more complicated because you have multiple elements inside. CKE5 architecture should be able handle your case but you have to understand that this is almost impossible to write without proper guides.
If you want to tinker though, you should study ckeditor5-image repo. It won't be easy, but this is the best way to go. Image plugin together with ImageCaption are very similar to your case.
Model:
<image alt="x" src="y">
<caption>Foo</caption>
</image>
View:
<figure class="image">
<img alt="x" src="y" />
<figcaption>Foo</caption>
</figure>
While in your case, I'd see the model somewhere between those lines:
<rankItem imageSrc="x" linkUrl="y">
<rankTitle>Foo</rankTitle>
<rankNotes>Bar</rankNotes>
</rankItem>
And I'd make the view a bit heavier but it will be easier to write converters:
<li contenteditable="false">
<a href="y">
<img src="x" />
<span class="data">
<span class="title" contenteditable="true">Foo</span>
<span class="notes" contenteditable="true">Bar</span>
</span>
</a>
</li>
For rankTitle and rankNotes - base them on caption element (ckeditor5-image/src/imagecaption/imagecaptionengine.js).
For rankItem - base it on image element (ckeditor5-image/src/image/).
Once again - keep in mind that we are in the process of simplifying all of this. We want people to write their own features, even those complicated ones like yours. However, we are aware of how complex it is right now. That's why there are no docs at the moment - we are looking to change and simplify things.
And lastly - you could create that ranking list simpler, using Link plugin and elements build with converter builder:
rankList -> <ol class="rank">,
rankItem -> <li>,
rankImage -> <img />,
rankNotes -> <span class="notes">,
rankTitle -> <span class="title">.
However, it will be possible to mess it up because the whole structure will be editable.
Model:
<rankList>
<rankItem>
<rankImage linkHref="" />
<rankTitle>Foo</rankTitle>
<rankNotes>Bar</rankNotes>
</rankItem>
...
</rankList>
Where "Foo" and "Bar" also have linkHref attribute set.
View:
<ol class="rank">
<li>
<img src="" />
<span class="title">Title</span>
<span class="notes">Foo</span>
</li>
...
</ol>
Something like this, while far from perfect, should be much easier to write as long as we are before the refactor and before writing guides.
Of course you will also have to provide view-to-model converters. You might want to write them on your own (take a look at ckeditor5-list/src/converters.js viewModelConverter() -- although yours will be easier because it will be flat, not nested list). Or you can generate them through converter builder.
Maybe it will be possible to use the approach above (simpler) but use contentEditable attribute to control the structure. rankList would have to be converted to <ol> with contentEditable="false". Maybe you could somehow use toWidget for better selection handling, for example. rankNotes and rankTitle would have to be converted to element with contentEditable="true" (maybe use toWidgetEditable()).

Dynamic display in Grails

I have this problem I'm facing. I have been working on a project using Grails based on the advice from a friend. I'm still a novice in using Grails, so any down to earth explanation would be highly welcomed.
My project is a web application which scans broken or dead links and displays them on a screen. The main application is written in Java, and it displays the output (good links, bad links, pages scanned) continuously on the system console as the scan goes on. I've finished implementing my UI, controllers, views, database using Grails. Now, I will like to display actively in a section of my GSP page say forager.gsp the current link being scanned, the current number of bad links found and the current page being scanned.
The attempts I have tried in implementing this active display include storing the output my application displays on the console in a table in my database. This table has a single row which is constantly updated as the current paged scanned changes, number of good links found changes and number of bad links found changes. As this particular table is being updated constantly, I've written an action in my controller which reads this single line and renders the result to my UI. The problem I'm now facing is that I need a way of constantly updating the result being displayed after an interval of time in my UI. I want the final output to look like
scanning: This page, Bad links: 8, good links: 200
So basically here is my controller action which reads the table from the database
import groovy.sql.Sql
class PHPController {
def index() {}
def dataSource
def ajax = {
def sql = new Sql(dataSource)
def errors = sql.rows("SELECT *from links")
render (view: 'index', template:'test', model:[errors:errors])
}
}
Here is the template I render test.gsp
<table border="0">
<g:each in="${ errors }" var="error">
<tr><td>${ error.address }</td><td>${ error.error}</td><td>${ error.pageLink}</td></tr>
</g:each>
</table>
For now I'm working with a test UI, which means this is not my UI but one I use for testing purposes, say index.gsp
<html>
<body>
<div><p>Pleaseeee, update only the ones below</p></div>
<script type="text/javascript">
function ClickMe(){
setInterval('document.getElementById("auto").click()',5000);
alert("Function works");
}
</script>
<div id="dont't touch">
<g:formRemote url="[controller:'PHP', action:'ajax']" update="ajaxDiv"
asynchronous="true" name="Form" onComplete="ClickMe()" after="ClickMe()">
<div>
<input id="auto" type="button" value="Click" />
</div>
</g:formRemote>
<div id="ajaxDiv">
<g:render template="/PHP/test"/>
</div>
</body>
</html>
The div I'm trying to update is "ajaxDiv". Anyone trying to answer this question can just assume that I dont have an index.gsp and can propose a solution from scratch. This is the first time I'm using Grails in my life so far, and also the first time I'm ever dealing with ajax in any form. The aim is to dynamically fetch data from my database and display the result. Or if someone knows how to directly mirror output from the system console unto the UI, that will also be great.
It sounds like a form would be appropriate for your needs. Check out the Grails documentation on forms. You should be able to render a form with the values you would like without too much trouble. Be sure to pay attention to your mapping and let me know if you have any questions after you have set index.gsp up to render a form for your values.

HTML Helper with HTML Helpers Inside

I'm trying to wrap my head around something; maybe someone here can point me in the right direction.
Currently a have a form that has some controls on it like this:
#Html.ListBoxFor(s => s.SomeListSelection1, new MultiSelectList(Model.SomeList1, "Id", "Text"))
<br />
#Html.ListBoxFor(s => s.SomeListSelection2, new MultiSelectList(Model.SomeList2, "Id", "Text"))
<br />
#Html.ListBoxFor(s => s.SomeListSelection3, new MultiSelectList(Model.SomeList3, "Id", "Text"))
<br />
This form appears in many places with some slight variation on which controls are available.
The "slight variation" makes me not just want to do this as a partial view as I will either need to replicate the controls into many slightly varied partials or code the variation logic into the view.
So I think, "I know, I'll use the cool HTML Helper thingy!!"
But, all the HTML helper samples online are very simple html content. So the question is how can I use other HTML helpers inside an HTML helper? Or, if that is the wrong question is there another cleaner alternative to just making this a partial view with a bunch of conditional rendering logic?
Edit:
While the answer did technically answer my question, I had trouble making use of the blog entries for what I was trying to do. I found a better example (for me anyway) here:
ASP.NET MVC 3 Custom HTML Helpers- Best Practices/Uses
Yes, you can.
Helpers can contain arbitrary Razor markup.
In fact, the direct contents of a helper method is a code block, not markup.
For a more in-depth discussion about how helpers work, see my blog.

Declarative AJAX "Controls" in MVC

I want to create a reusable ajax control in MVC .NET using RAZOR.
my example is a simple ajax text box and list where the user filters the list by typing in the text box. on the first call i would render both the text box and the list using my razor view. on subsequent AJAX calls i would want to ONLY render the (now filtered) list.
idea 1: use #if statement to conditionally render code.
problem: razor does not seem to like conditionally written html. for example it errors when a <div> tag is not followed by a closing </div>.
idea 2: use #section tokens to create portions of my control and then call RenderSection within the same file as needed.
problem: razor does not allow RenderSection to call sections in the same page
i know i can conditionally render html as strings, but i wanted to take advantage of the legibility of the razor markup and keep with development protocols.
You should be able to output <div> tags in a Razor block without the corresponding </div> tag by surrounding it with <text>. The reason is that Razor uses the closing tag to know when to drag back into code-parsing mode:
#if (myCondition)
{
<text>
<div>
</text>
}
As for the Section stuff, you might be able to achieve what you want using Templated Razor Delegates, like this:
#{
Func<dynamic, object> b = #<strong>#item</strong>;
}
// ...
<span>This sentence is #b("In Bold").</span>
See Phil Haack's blog for a little more on this.

Razor Nested Layouts with Cascading Sections

I have an MVC3 site using Razor as its view engine. I want my site to be skinnable. Most of the possible skins are similar enough that they can derive from a shared master layout.
Therefore, I am considering this design:
However, I would like to be able to call RenderSection in the bottom layer, _Common.cshtml, and have it render a section that is defined in the top layer, Detail.cshtml. This doesn't work: RenderSection apparently only renders sections that are defined the next layer up.
Of course, I can define each section in each skin. For instance, if _Common needs to call RenderSection("hd") for a section defined in Detail, I just place this in each _Skin and it works:
#section hd {
#RenderSection("hd")
}
This results in some duplication of code (since each skin must now have this same section) and generally feels messy. I'm still new to Razor, and it seems like I might be missing something obvious.
When debugging, I can see the complete list of defined sections in WebViewPage.SectionWritersStack. If I could just tell RenderSection to look through the entire list before giving up, it would find the section I need. Alas, SectionWritersStack is non-public.
Alternatively, if I could access the hierarchy of layout pages and attempt execution of RenderSection in each different context, I could locate the section I need. I'm probably missing something, but I don't see any way to do this.
Is there some way to accomplish this goal, other than the method I've already outlined?
This is in fact not possible today using the public API (other than using the section redefinition approach). You might have some luck using private reflection but that of course is a fragile approach. We will look into making this scenario easier in the next version of Razor.
In the meantime, here's a couple of blog posts I've written on the subject:
http://blogs.msdn.com/b/marcinon/archive/2010/12/08/optional-razor-sections-with-default-content.aspx
http://blogs.msdn.com/b/marcinon/archive/2010/12/15/razor-nested-layouts-and-redefined-sections.aspx
#helper ForwardSection( string section )
{
if (IsSectionDefined(section))
{
DefineSection(section, () => Write(RenderSection(section)));
}
}
Would this do the job ?
I'm not sure if this is possible in MVC 3 but in MVC 5 I am able to successfully do this using the following trick:
In ~/Views/Shared/_Common.cshtml write your common HTML code like:
<!DOCTYPE html>
<html lang="fa">
<head>
<title>Skinnable - #ViewBag.Title</title>
</head>
<body>
#RenderBody()
</body>
</html>
In ~/Views/_ViewStart.cshtml:
#{
Layout = "~/Views/Shared/_Common.cshtml";
}
Now all you have to do is to use the _Common.cshtml as the Layout for all the skins. For instance, in ~/Views/Shared/Skin1.cshtml:
#{
Layout = "~/Views/Shared/_Common.cshtml";
}
<p>Something specific to Skin1</p>
#RenderBody()
Now you can set the skin as your layout in controller or view based on your criteria. For example:
public ActionResult Index()
{
//....
if (user.SelectedSkin == Skins.Skin1)
return View("ViewName", "Skin1", model);
}
If you run the code above you should get a HTML page with both the content of Skin1.cshtml and _Common.cshtml
In short, you'll set the layout for the (skin) layout page.
Not sure if this will help you, but I wrote some extension methods to help "bubble up" sections from within partials, which should work for nested layouts as well.
Injecting content into specific sections from a partial view ASP.NET MVC 3 with Razor View Engine
Declare in child layout/view/partial
#using (Html.Delayed()) {
<b>show me multiple times, #Model.Whatever</b>
}
Render in any parent
#Html.RenderDelayed();
See the answer link for more use-cases, like only rendering one delayed block even if declared in a repeating view, rendering specific delayed blocks, etc.

Resources