How to handle html templates in MVC2? - asp.net-mvc-2

My (MVC2) application displays several addresses in a View.
Each address contains just a subset of information, like first- and lastname. The request is that the complete address information should be displayed when the mouse is over a result.
An html template should be used therefor.
This template defines how(!) the complete address should be displayed – but it doesn’t defines what(!) should be displayed.
Means it can be assumed that the complete address is always “firstname“, “lastname”, “street”, “zipcode” and “city” (for example and to keep it simple). This will never be changed.
But for example the background color can be changed in the html template from white to green or the size of the lastname can be changed from <h1> to <h2> …
What is the best way to solve it?
I would prefer to write some shared code (keyword: ascx).
This shared code should wrap the template, would be very easy and would look like this:
<div id=”mouseOver” style="display: none;" >
X_REPLACE_X
</div>
The template would look like this simplified example:
FirstName: {Name}<br/>
Lastname: <h1>{Lastname}/<h1><br/>
ZipCode: {ZipCode}<br/>
I would then render the ascx code via “Html.RenderPartial” on the View and map each address to a javascript mouseover function.
The javascript function would replace the placeholder (like {FistName}, {LastName} , etc.) in the template, position and display it.
And thats my problem:
The template should NOT be put directly in the wrapper (ascx - code)!
Means at runtime must “X_REPLACE_X” be replaced with a somewhere on the server stored template.
Because this gives me the ability to change the template without changing and publishing the code!
How can this be managed?
Is there a much better way to solve it? Should I use instead ajax calls to get the template in a variable?
Any help would be really great!
thxs in advance!

It sounds like the best way to accommodate your display differences is to simply use different css classes. The html template used for the full information does not change and can be used for all addresses, while the differences between background colors and text size can be handled by different css settings.
Relatedly, I wouldn't handle the different text sizes by using <h1></h1> and <h2></h2> but rather a common tag (such as <span></span>) whose text size is handled via css.

Related

How do you AB test with Google Optimize on elements that have dynamic variables?

Im currently using Google Optimize's editor and I need to make an edit on an element that contains some dynamic variables. However when I edit the html, it renders the plain text and therefore it updates without the dynamic variable in place.
For example in the code it might be set up as <p>{{ user.name }}</p> but when I use the editor to edit the html it will show it as <p>John Smith</p> but if I apply changes it will replace my dynamic variable with the plain text.
Is there a solution for this?
You can try instead of editing the HTML via replace, you can insert/append/prepend.
Of course, this might mean you need to do some clever things with your code. Provide the before and after in your question and we can talk specifics.
Another thing you can try is to not use edit HTML and just use the editor to change the styling.

Getting an element defined in a core:html by its ID

I used this line to define a canvas element in my view.xml:
<core:HTML content="<div class="wrapper col-6"><canvas id="
myChart"width="800"height="400"></canvas></div>">
</core:HTML>
Now I want to get the element in the controller but the typical this.getView().byId("myChart") doesn't seem to work even though the site successfully loads a canvas with the ID.
Is there a way to get those types of elements defined inside a core:HTML tag for the controller?
If not, is there a different way to create a canvas or other HTML elements so that I can refer to them with an ID / use them in the controller?
The element created in this way is not 'registered' in UI5 framework like the other controls. byId() only checks the internal register.
You can use jQuery or standard JavaScript to fetch the element though, like $('#myChart') or document.querySelector('#myChart').
You will find the code for this in Core.js or Core-dbg.js.
Like Jorg said, byId is for retrieving controls. So if you were to put an id on the HTML control, you could retrieve that control and then call getDomRef() on it to get the outermost element, which in your example would be the div. If you'd further only put the canvas inside the HTML control, you'd get that.
If you're accessing the id of the canvas directly, like Jorg suggested, you'll run into trouble if you're going to use the view twice inside a page, because the id of the canvas isn't unique anymore.
There is a third and IMHO preferable option, that is to use html directly inside the view. First you'll need to declare a namespace for it, like
xmlns:html="http://www.w3.org/1999/xhtml"
preferably right on your View element.
Then you can write html directly in your xml view like this:
<html:div class="wrapper col-6">
<html:canvas id="mycanvas" width="800" height="400"></html:canvas>
</html:div>
This way you're getting a proper (unique) id for your canvas and can access it as part of the view's dom with this.getView().getDomRef("-mycanvas"). Note the extra leading dash, because of internal id generation inconsistency in UI5. Also note that getDomRef() is considered protected, but I doubt it will change. Finally, remember that you can only get a domref for rendered controls, so you'll probably want to access it from an afterRendering event.

Automated material UI components using watir or selenium

I am trying to find out if anyone has an approach to automated UI testing on Material UI components.
Material UI elements are rendered as nested divs with very little unique id information, for example:
<div data-reactroot style="...">
<div style="...">
<div style="...">
</div>
</div>
</div>
The nested div structure makes using traditional location methods difficult if not impossible - (Selenium and Watir), id, name, class, etc.
Using react devtools, one can see a much clearer picture of how the page is structured, but I am not yet able to access the React "DOM" to locate elements.
Any ideas or help would be appreciated.
Added example:
Sliders
I can't come up with an example that is more descriptive than the one above, could literally be 10 layers of nested divs without any text.
There is no general method I'm aware of, unfortunately.
Some of the components already have ids, which allows you to use a css selector like #my-component input (which is usually enough to get an exact field), others have custom class names to be added (like AutoComplete - popoverProps) which allows you to use a similar selector.
Good news is that every MaterialUI component provides className, which can be used to locate elements (at least partially) - details can be found at http://www.material-ui.com/#/customization/styles
Also id field works quite often, even when not documented.
At the last resort (if detection by class + other css selector parts is not sufficient) you can fall back to XPath expression using element text - for example, I use //span[#class="menu-item"][.//div[contains(text(),"${itemName}")]] for matching menu items. It matches things declared as <MenuItem primaryText={itemName} className="menu-item">

jQuery Show/Hide divs using same class not working because of html.push?

The object is to Show-Hide text located under their respective Titles, so a User reads the title and shows or hides text belonging to that title if the User wants to read more.
I tried whatever I could find so far on here, we're talking dynamically setting text coming from a spreadsheet, can't use IDs, must work with .class, must be missing something, I have this piece of code:
... html.push('<div class="comments">' + comment + '</div></div></div>');
but when I try this Show-Hide code nothing happens, even if the error console shows nothing. Basically I want to Show-Hide the .comments class divs with a show-hide toggle link located under each of them. I say them because the .comments divs are reproduced dynamically while extracting text coming from Google spreadsheet cells/row (one .comments div per spreadsheet row). I tried .next, child and parent but they all divorced me so I dunno looks like a dynamic issue. So far I only managed to globally toggle all divs to a visible or hidden state but I need to toggle independantly individual divs.
I prefer a jQuery solution but whatever worked so far was achieved with native javascript.
Note: If a cross-browser truncate function which would append a more-less link after a number of words (var) in each .comments divs would be easier to implement then I would gladly take that option. Thx for any help, remember I am still learning lol!
I have been working on an entirely JS UI project and have brought myself to using $('', { properties }).appendTo(BaseElement) to work best for adding HTML elements because it appropriately manipulates the DOM every time.
If you are having good luck with push elsewhere, however, breakpointing on the line where you do your $('.class').hide() and see what $('.class').length is. Alternately, you can just add alert($('.class').length) to your code if you are unable to breakpoint the code. If it is 0, then your elements have not been properly added to the DOM. Changing to append will ensure they are part of the DOM and therefore targetable via JQuery.

ASP.NET MVC2 - Determine which type of template is being rendered

Instead of using DisplayFor and EditorFor, I would like to create a more generic ContentFor. In that Html extension it would take into account Metadata values to determine how to render the resulting control. The only piece of the puzzle I am not am to determine is this: Is there a way to determine if I am currently rendering a DisplayTemplate or an EditorTemplate. As a real-world example of this, when rendering a string, for the display version I would like to render it as a , but when rendering the editor version, I would want to render it as a text box.
To better explain, let's say I have two templates called Address.ascx, one in the DisplayTemplates directory and one in the EditorTemplates directory. I would like both of them to use ContentFor to render, but in the display version it renders as a label and in the editor version it renders as a textbox.
Using two ASCX files to call a single file control (which is doable, just do another RenderPartial or DisplayFor/LabelFor) doesn't make sense to me. It breaks the "seperation of concerns". Label displays labels, and Display displays values, it doesn't make sense for a control to try and figure out what way you want it to display.
If you want a use a custom display or label for a property, use the UIHint data Annotation.
[UIHint("MyCustomControlName")]
Then in the DisplayTemplates and EditorTempaltes create a "MyCustomControlName.ascx" file to display that property however you want. Additionally, the ascx controls can read custom Model Metadata and do whatever it is you need done. Example at http://weblogs.asp.net/seanmcalinden/archive/2010/06/11/custom-asp-net-mvc-2-modelmetadataprovider-for-using-custom-view-model-attributes.aspx.