I have some markup I would like to cover with a simple wrapper. In this case, the idea is to wrap two <input> elements within some markup, so that this markup:
<div class="group-class">
<div class="first-class">
<input id="first">
</div>
<div class="second-class">
<input id="second">
</div>
</div>
would be marked up like this instead:
<my-wrapper>
<input id="first">
<input id="second">
</my-wrapper>
I initially thought of a component, but that would create a shadowDOM, and thus would not behave the same way as if <my-wrapper> didn't exist. <my-wrapper> tag should replace itself with the content of the first example, so that the DOM rendered is the same. I believe I saw some replace option for an angular-directive, but I am very unsure how to do this.
Related
I'm creating a couple of thymeleaf fragments to use in other pages, and I was told they need to be inside a well-formed html page (with HTML, HEAD, BODY tags etc). Is this the case?
The fragments are only going to be used with th:include/th:replace in other places.
A fragment just needs to be a well formed html. You can start with a div
For e.g
<div th:fragment="formField (field, value, size)">
<div>
<label th:for="${#strings.toLowerCase(field)}"> <span
th:text="${field}">Field</span>
</label>
</div>
<div>
<input type="text" th:id="${#strings.toLowerCase(field)}"
th:name="${#strings.toLowerCase(field)}" th:value="${value}"
th:size="${size}">
</div>
Which you then include somewhere else
<body>
<header th:insert="fragments/general.html :: header"> </header>
<div th:replace="fragments/forms.html
:: formField(field='Name', value='John Doe',size='40')">
</div>
<div th:replace="fragments/general.html :: footer"></div>
I took these examples from here: https://www.baeldung.com/spring-thymeleaf-fragments
I am trying to create a re-usable UI element in ASP.NET MVC that wraps around whatever content I choose to place in it. My first thought was to create a partial view, but that doesn't seem to help me in what I am trying to accomplish.
The Template
For example I would like to create some re-usable markup similar to this (please excuse the pseudo-code):
<div class="panel panel-default">
<div class="panel-body">
#RenderBody()
</div>
</div>
A Simple Example
Then in my views I would like to do something similar to this:
#Render.Partial("MyPanel")
{
<img src="image.jpg" />
}
Assuming that code worked as expected it would generate the following:
<div class="panel panel-default">
<div class="panel-body">
<img src="image.jpg" />
</div>
</div>
Another Example, with more complex markup
Theoretically I would like to be able place any and everything I would like within one of the panels. So even more complex markup would still appear legible.
#Render.Partial("MyPanel")
{
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<div class="form-group">
<label for="exampleInputFile">File input</label>
<input type="file" id="exampleInputFile">
<p class="help-block">Example block-level help text here.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
}
Just like in the first example, it would wrap everything inside the header and footer of my template:
<div class="panel panel-default">
<div class="panel-body">
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
.. truncated ..
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
Known Possibilities
Partial View. A partial view seems to make sense, except I have been unable to figure out a way to create a partial that has flexibility beyond the Model it was designed for. I gave two examples, because the contents within my panel could be significantly different each time I use it. I would like to be able throw anything into the body of this partial view; text, markup, more razor code, etc.
HTML Helper. This works great when I have specific parameters I would be passing in. I don't see this as practical when needing to enter large amounts of markup, as it would become hard to read/maintain. Also since html would be passed in as a string, I'm not sure how this would work with razor tags?
2 Partial Views. Using one as the header and the other as the footer. This works, but it just feels sloppy to me.
I was able to do this in ASP.NET WebForms by creating a custom control. It seems like this is something that should be straight forward in MVC too, but I just haven't quite been able to figure out a good solution yet.
You can use "DynamicInvoke" to create html helpers with dynamic markup, such as:
public static IHtmlString CustomPanel(this HtmlHelper htmlHelper, Func<object, object> panelMarkup = null)
{
return CustomPanel(htmlHelper, (panelMarkup == null ? "" : panelMarkup.DynamicInvoke(htmlHelper.ViewContext).ToString()));
}
public static IHtmlString CustomPanel(this HtmlHelper htmlHelper, string content)
{
TagBuilder div = new TagBuilder("div");
div.AddCssClass("panel panel-default");
TagBuilder innerDiv = new TagBuilder("div");
innerDiv.AddCssClass("panel-body");
innerDiv.InnerHtml = content;
div.InnerHtml = innerDiv.ToString();
return new HtmlString(div.ToString());
}
And then you would use it like this:
#Html.CustomPanel(
#<text>
<div>My Custom Markup</div>
<span>More Stuff</span>
</text>
)
Your final content will look like:
<div class="panel panel-default">
<div class="panel-body">
<div>My Custom Markup</div>
<span>More Stuff</span>
</div>
</div>
You see this used often in some 3rd party widget libraries (kendo-ui is the main one i know of)
There are many ways to create reusable content in MVC, but they all have various pros and cons. For instance, custom Html helpers are a common method, but they require writing a lot more code than you probably want.
You can certainly use partial views, just pass a model containing the content you want to render to the partial... but that can also be a little confusing as well.
I think what you may be looking for are Razor Helpers. These are explained in more detail here:
http://weblogs.asp.net/scottgu/asp-net-mvc-3-and-the-helper-syntax-within-razor
However, the basic structure would look like this:
#helper MyHelper(string content)
{
<div class="panel panel-default">
<div class="panel-body">
#Html.Raw(content)
</div>
</div>
}
Then you use it like this:
#MyHelper("<img src="image.jpg" />")
You don't have to use strings, you could use structured content, models, etc.. you can use other helpers inside. You can re-use them as described later in the article.
You might want to start thinking about your pages as more data-centric, however. If you use EditorTemplates to render your data then you render controls based on the type of your data rather than rendering your pages and trying to adapt your pages to contain your data.
My index.html contains the following element
...
<div class="col-md-6" ng-bind-html='module.docs.html'></div>
...
The module.docs.html property returns HTML like
<div ng-controller="accordion-demo-ctrl">
<label class="checkbox">
<input type="checkbox" ng-model="oneAtATime">
Open only one at a time
</label>
<accordion close-others="oneAtATime">
<accordion-group heading="Static Header, initially expanded" is-open="true">
This content is straight in the template.
</accordion-group>
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
<accordion-group heading="Dynamic Body Content">
<p>The body of the accordion group grows to fit the contents</p>
<button class="btn btn-default btn-sm" ng-click="addItem()">Add Item</button>
<div ng-repeat="item in items">{{item}}</div>
</accordion-group>
<accordion-group is-open="isopen">
<accordion-heading>
I can have markup, too! <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': isopen, 'glyphicon-chevron-right': !isopen}"></i>
</accordion-heading>
This is just some content to illustrate fancy headings.
</accordion-group>
</accordion>
</div>
The HTML is inserted but Angular.dart seems not to do anything with it (accordion-demo-ctrl is not instantiated)
Using the ng-include directive worked.
I changed my code so that I provided the URI of the HTML fragment instead of the source itself (fetched from the server anyway).
see also my answer to How to add a component programatically in Angular.Dart? for an alternative solution
In my cshtml file I have a form named 'ApplyMedicalMain' and I want to show a dynamically loaded division when the form is dirty but its not happening even though the form is dirty ...
Below is my code that i got in Firefox Inspect Element:
<form class="form_section ng-dirty ng-valid ng-valid-required" name="ApplyMedicalMain" method="post" action="/MVC/Quote/ApplyMedical">
<div id="Step1_PartialView" class="QuoteStep1">
<script type="text/javascript" src="/Scripts/Renderings/Presales/ApplyMedical.js">
<div name="Conditions" id="conditions_or_symptoms" ng-hide="ApplyMedicalMain.$dirty">
<div class="generic_error_message select">
<div class="error_icn_message"></div>
</div>
As you can see above, I have mentioned ng-hide for the division name='conditions' but it is not getting hidden even though the form has class 'ng-dirty'.And please note that the the division 'conditions' is loaded dynamically from other partial view.
can someone help me ?
You forgot to wrap everything in a 'ng-app' container, here is a working example (I cleaned a bit the code)
<div ng-app>
<form class="form_section ng-dirty ng-valid ng-valid-required" id="ApplyMedicalMain" method="post">
<div ng-hide="ApplyMedicalMain.$dirty">Hidden when dirty</div>
<div ng-show="ApplyMedicalMain.$dirty">Shown when dirty</div>
</form>
</div>
I'm not entirely sure why your example isn't working, but I would suggest you use css to do your hiding/showing rather than using angular's bindings:
form.ng-dirty .hide-on-dirty{
display:none;
}
And then:
<form class="form_section ng-dirty ng-valid ng-valid-required" name="ApplyMedicalMain" method="post" action="/MVC/Quote/ApplyMedical">
<div id="conditions_or_symptoms" class="hide-on-dirty"> ... </div>
</form>
That's a bit more efficient that creating a binding to the form controller's state. But its just a thought. There might be more of a reason why you're wanting to do the binding.
.I have a div tag that is also divided into two divs. here is the code:
<div>
<div id="search">
<form id="try" method="post">
Batch: <input id="batch" name="batch" type="text"/>Dept: <input id="dept" name="dept" type="text"><input type="submit"/>
</div>
<div id="receiver">
</div>
</div>
I have placed a search option in the div named "search" using post method. what i want to do is that when i click the submit button the page to receive the values will appear on the div named "receiver".
is this possible? if it is, please help..
The ways you have for this are:
1 - The simplest - instead of a div - use an IFrame like this
<div id="search">
<form id="try" method="post" target="receiver" action="url-to-server-Page">
Batch: <input id="batch" name="batch" type="text"/>
Dept: <input id="dept" name="dept" type="text" />
<input type="submit"/>
</form>
</div>
<iframe name="receiver" id="receiver"></iframe>
</div>
The disadvantage in this case is that the search-result that come in this case from url-to-server-page - is a complete and independent HTML page that is nested in your search page.
It is not effected by styles of the parent page, and the communication between them for JavaScript operations is rather combersome.
2 - with some JavaScript skills you can use AJAX.
There are many libraries on the net that can help you do it in very few lines of code.
jQuery is the simplest, although it's the one I like least...
http://jquery.com/
3 - use a full round-trip
<div id="search">
<form id="try" method="post" target="receiver" action="url-to-server-Page">
Batch: <input id="batch" name="batch" type="text"/>
Dept: <input id="dept" name="dept" type="text" />
<input type="submit"/>
</form>
<div id="receiver">
<?php if (isset($_POST['batch']) && isset($_POST['dept'])){
//display search results here.
}
?>
</div>
</div>
You want what's called "AJAX." There are a number of libraries available, such as Google Web Toolkit or jQuery to accomplish what you want.
Can you clarify? Is this a php page and you are posting to self or are you looking to use ajax to populate the div?
If it is php and you post to self then you can simply check if the post has been made inside that div :
<div id="receiver">
<?php if (isset($_POST['batch']) && isset($_POST['dept'])){
//display search results here.
}
?>
</div>