Multiple views for 1 controller - Play Framework [duplicate] - html

If i want to have a common piece of UI across multiple pages, such as a menu, what is the recommended way to do this?
It would contain both template code and a back-end controller (similar to "snippets" in the LiftWeb framework).
I am aware that there is a menu module for Play, but I'm more interested in how this would be achieved in general.

There are two ways to include common view code into the Play Framework.
You can use the #{include} tag or the #{extends} tag.
The extends tag, as the name suggests, extends from a parent view. The extends tag is used by default in the skeleton code set up by Play when you create a new application. It extends the main.html. You add your code here.
The includes tag, allows you to inject a common piece of view code into your templates at a specified point. This works in much the same was a php include/require, or jsp includes work.
The problem will come when your template code also requires data or logic from the model (via the controller). If this is the case, then you will need to use the #Before or #With notation in your controller to ensure that the common piece of controller code is executed each time. You can add any data to the renderArgs list, so that it is available for use within the view.
A simple example of using renderArgs would be.
#Before
private static void commonData() {
// do your logic here
renderArgs.put("menu", menu);
renderArgs.put("selected", selectedMenuItem);
}
the values you have put into renderArgs (menu and selected in the example) will be available just in the same way as if you passed them into the render method.

Related

Angular 2+ multiple HTML template for one component

I have the following scenario. I am writing a complex component that is using three-js:
The component manages complex mouse interactions and updates other elements in the DOM using two-ways data binding: variables, JSON objects, mouse interactions, etc.
I start using the component in few part of my application but I needed to substantially modified the threed-viewer.html so I made a copy of the whole component ending up having duplicates that are hard to maintain.
All flavours of the component share 80% of the javascript code and bindings but they have substantial UI differences. So I had the though of create different 3 basic component (minimal javascript code) that I can inject into the threed-viewer.html using a selector and a variable to decide which template to load:
this does not compile as the html files have all the variables and bindings from the original components but they are not present in the typescript files.
Another solution could be to have a single html managed via ngIf but it will result in a long, messy, difficult to manage file. Is this the only option I have in Angular. Any other idea?
Thank you.
You can have a shared service and then add three different components but js code won't be duplicated as it will be in the service.
Use two way bindings in all 3 components using the service variables, functions and objects
I have did long time ago - the pages and article editor. Two different templates, same code.
I used articles component as "parent", and extended it to news editor.
Looks like this:
#Component({template: 'blah blah blah'}) export class parent {}
#Component({template: 'blah2 blah2 blah2'}) export class child extends parent {}
Hopefully this is the solution you were looking for.
Two different components, two templates, one code.
Of course, you can have the "parent" abstract class for both where you can save all methods you need.
It's OOP baby ;)

Use of #{if-else} tags in PLAY templates

I am working since last few months with PLAY 1.2.5 using Java and HTML for views. I am aware of using JAVA code in PLAY templates using %{ if ------else}% (kind of as we use scriplets in J2EE. But now I came across use of tags like #{if}---{/if}. I searched around and found that this also is a way of using if-else. But my query is that in a similar piece of code I saw the following:
#{if some variable value in Controller == 'true'} ------- #{/if} #{else}------ #{/else} .
Now I don't understand how this Controller variable is accessed in controller within these tags. I have looked around and found that no such variable was rendered by render() or renderArgs() from the controller.
Is there any other way of using those variables/methods on templates which are declared in controllers or model for that matter?

Passing Razor Markup to view and process it

I've searched the internet for days now with no luck finding this.
My model has a property which holds a chunk of html containing Razor markup.
exmaple:
public class ViewModel
{
public string Content = "<div>#Html.TextBox(\"UserName\")</div>";
}
In the view, I display that with
#Html.Raw(Server.HtmlDecode(Model.Content).toString())
I need to be able to convert the Razor markup into html, although because the Content is dropped in through the model, the view engine doesn't process it.
I have tried simply dropping in the Content, using just .Raw(Model.Content), .Encode(Model.Content), nothing works.
Any thoughts?
You could use the RazorEngine package which allows you to parse and execute Razor code. This being said I would not recommend you giving your users the power of editing directly Razor templates. You are opening a huge security hole in your website.
There are other templating engines such as DotLiquid for example which are better suited for scenarios where you don't trust user input.

ASP.NET - Using HAP (HTML Agility Pack) to Add Class References During Render

Is it possible to use the HAP (HTML Agility Pack) to:
Grab a collection of nodes e.g. all <a> elements which are children of <li> elements
Iterate over the collection
Add CSS class references into the class attribute for each element e.g. class &= "foo"
Update the nodes in their original position within the HTML
For point 4, I need to know whether:
When I grab a collection of nodes, am I working with copies?
If so, can I easily update the nodes in their original position within the HTML
Finally, would it be practical to do this when rendering a page in an ASP.NET website, considering:
I will need to modify the class references for no more than 100
elements
I am not working with large HTML documents
I plan to select my nodes starting at a div e.g. div[2] where body
contains 4 divs
I realise that this may seem like a bunch of separate questions but really it is just a breakdown of the following two questions:
Can I easily modify the HTML output of an ASP.NET page e.g. to insert class references?
Would it be practical to do this on 50 - 100 elements WRT speed e.g. no more than 2 seconds cost?
Many thanks.
Check out my CsQuery project: https://github.com/jamietre/csquery or on nuget as "CsQuery".
This is a C# (.NET 4) port of jQuery. Selectors are orders of magnitude faster than HTML Agility Pack; in fact, my initial purpose in writing it was to do exactly what you want to do: manipulate HTML in real time. As it happens, from a CMS with html generated by ckeditor.
To intercept HTML in webforms with CsQuery you do this in the page codebehind:
using CsQuery;
using CsQuery.Web;
protected override void Render(HtmlTextWriter writer)
{
// the CsQueryHttpContext object is part of the CsQuery library, it's a helper
// than abstracts the process of intercepting base.Render() for you.
CsQueryHttpContext csqContext =
WebForms.CreateFromRender(Page, base.Render, writer);
// CQ object is like a jQuery object. The "Dom" property of the context
// returned above represents the output of this page.
CQ doc = csqContext.Dom;
doc["li > a"].AddClass("foo");
// write it
csqContext.Render();
}
There is basic documentation on GitHub, but apart from getting HTML in and out, it works pretty much like jQuery. The WebForms object above is just to help you handle interacting with the HtmlTextWriter object and the Render method. The general-purpose usage is very simple:
var doc = CQ.Create(htmlString);
// or
var doc = CQ.CreateFromUrl(url);
.. do stuff with doc, a CQ object that acts like a jQuery object
string html = doc.Render();
Don't do that ! ASP.NET is not meant to be used that way, there is a better ways to do this task depending on how do you create that markup in witch you want change or add css classes. ASP.NET uses aspx templates, basically html markup and there you can intervene with code executing on server, here you can set css class statically or use server side scripts to set css class on markup with some code.
You can also create controls in code behind and set css to controls if anchor control have parent that is list item control (you will have to use server side controls).
To do it your way you will have to make Response Filter (example here) and after request is done do your parsing and write results and changes back to response stream. It's much easier using common ASP.NET techniques.

How to append a custom HTML attribute or CSS class using a .NET data annotation attribute?

I'm using ASP.NET MVC 3 RTM. Is it possible to change the HTML rendered from a View Model, by using an attribute?
Example:
public class Product
{
[AddHtmlAttribute(Name = "disabled", Value = "disabled")]
public string Name { get; set; }
}
I want the attribute to be able to change the rendered HTML, that property results in. I know it properly can't be done with an attribute alone. I probably have to hook into the system by implementing an interface, but where should I look?
I know MVC uses the default editor templates, and I've looked at them in the MVC 3 source code, but I haven't been able to figure out if it would be possible to somehow hook into the rendered element and add some attributes. I know the validation system does this, by adding custom HTML attributes to support unobtrusive validation.
I guess I just need a pointer to where I should look, or what interface I should take a look at.
Thank you so much.
Update: I'm using the standard HTML helper Html.EditorFor(model => model.Name) for my fields, and haven't overriden any editor templates. I would really prefer if I didn't have to change or override the default templates.
You may checkout the following blog post which illustrates how to achieve this by writing a custom DataAnnotationsModelMetadataProvider, attribute and overriding the default templates.