My ASP.NET MVC application includes a Razor view with 3 tabs with a bunch of fields.
tab 1-2 has a bunch of fields
tab 3 should have a file upload section which should be rendered from a partial view.
Here is the structure:
<body>
<div class="container well" >
#using (Html.BeginForm(new { Action = "action X",id="publishingForm" })) {
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="form-horizontal">
<div class="tabbable">
<ul class="nav nav-tabs">
<li class="active"><span><strong>Step 1:</strong></span> Enter required fields</li>
<li><strong>Step 2:</strong> Enter optional fields</li>
<li><strong>Step 3:</strong> Upload your video</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="requiredtab">
</div>
<div class="tab-pane" id="optionaltab">
</div>
<div class="tab-pane" id="uplaodtab">
partial view here
</div>
</div>
</div>
</div>
}
</div>
</body>
</html>
As you can see the tab Divs are wrapped in a form (post to Controller X).
The problem is the partial view for the file upload also includes a form which should post to a handler. But when I initiate a file upload in Tab 3 it is attempting to post to Controller X of the original form.
How can I structure my view to have the fields included in the form on tabs 1 & 2 post to Controller X and the Form in Tab 3 post to its correct handler?
The bottom line is I am trying to post separately to 2 different forms included in different tab panels
i suggest that you wrap your two forms with Ajax Forms, and you can submit them both asynchronously
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "updateDiv" }))
{
<input type="submit" id="submitForm1" value="OK" />
}
<div id="updateDiv"></div>
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "updateDiv2" }))
{
<input type="submit" id="submitForm2" value="OK" />
}
<div id="updateDiv2"></div>
and call the .click() for each submit button whenever your code needs to.
Related
Working on a site that has a structure of a main navigation that is defined in my shared "_Layout.cshtml" page and links on the main nav that will take you to different pages that have a separate navigation bar that is unique to that page.
(something like this^).
Currently I just have my second nav and main content all on the same page and have a ton of different tabs with Html.Actions rendered and they are toggled by clicking a link on the second navigation and changing the tab. This works but it makes my initial page load extremely slow since I believe they are all being loaded at once.
Html for tabs:
<div class="tab-content">
<div class="tab-pane fade in active" id="tab1" role="tabpanel">
<div class="container-fluid">
#Html.Action("tab1", new ViewDataDictionary { { "item", m.item }, { "item2", m.item2 } })
</div>
</div>
<div class="tab-pane fade in" id="tab2" role="tabpanel">
<div class="container-fluid">
#Html.Action("tab2", new ViewDataDictionary { { "item", m.item }, { "item2", m.item2 } })
</div>
</div>
<div class="tab-pane fade" id="tab3" role="tabpanel">
<div class="container-fluid">
#Html.Action("tab3", new ViewDataDictionary { { "item", m.item }, { "item2", m.item2 } })
</div>
</div>
<div class="tab-pane fade" id="tab4" role="tabpanel">
<div class="container-fluid">
#Html.Action("tab4", new ViewDataDictionary { { "item", m.item }, { "item2", m.item2
} })
</div>
</div>
Is there any alternative that would be better for a layout that has multiple secondary navigation bars that change depending on the link clicked on the "_Layout.cshtml" page?
Thanks for any help or ideas.
If you have complex pages that are getting loaded all in advance, and this is slow...alternatives would be:
Make the tabs just links to other pages that use the same tabs on them but aren't actually loaded. This will look the same, but--naturally--navigating from one tab to the next will be slower since everything isn't pre-loaded.
Use javascript to dynamically load the content when the user clicks on the tab. E.g. using jQuery.load(). This has more complexity but fits better with your current setup.
some friends and I have started a team project but we are stuck at this point. We made a function of the site to add comments under every post. The problem is that when submit is clicked it adds the comment but doesn't refresh the page which causes some problems. The author stays "anonymous" and when refresh button is clicked it shows an alert:
The page that you're looking for used information that you entered. Returning to that page might cause any action you took to be repeated. Do you wish to continue?
However, if we just type the URL again and click ENTER everything is good: the author shows up and the comment appears only once. So the only solution for us is to redirect to the same page. Here is the form:
<div style="text-align: left">
<div><i>Leave your comment</i>
</div>
<form method="post">
<fieldset>
<p>
<textarea rows="10" class="form-control" type="text" id="1" name="commentText" style="height: 100px"></textarea>
</p>
<p>
<input type="submit" name="buttonSubmit" onclick="redirect" value="Add comment" class="btn btn-default" style="" />
</p>
</fieldset>
</form>
</div>
This is how the comments are printed on the page:
<h3>Comments</h3>
<br>
<div>
#foreach (var comment in ViewBag.Comments) {
<section class="row">
<article class="post col-md-12">
<div class="about">
Posted on <i>#comment.Date</i>
#if (comment.AuthorId != null) { #: by <i>#comment.Author.FullName</i>
}else { #: by <i>anonymous</i>
}
</div>
<div class="body">#comment.Text</div>
</article>
</section>
}
</div>
Thanks in advance!
Use the #Ajax.BeginForm() helper.
In the AjaxOptions(), you'll want to set the Httpmethod to "Post", InsertionMode.InsertBefore (or After depending on where you want new comments), and UpdateTargetId = "your-comment-div".
You'll need to include jquery.unobtrusive-ajax.js so the Ajax helper works correctly. You can use the nuget package manager to pull it in. Be sure to add it to your jquery bundle.
Then, you need to create the post action in your controller to accept the comment params and return a partial view.
Doing thIs keeps the Ajax confined to a razor helper and controller method.
View:
#using (Ajax.BeginForm("AjaxAddComment",
"MyController",
/* route params */,
new AjaxOptions()
{
InsertionMode = InsertionMode.InsertBefore,
UpdateTargetId = "commentsDiv",
HttpMethod = "Post"
}, htmlAttributes: new { /* ... */ }))
{
<div class="form-horizontal">
#* comment form... *#
</div>
}
...
<div id="commentsDiv">
<div class="comment">...</div>
<div class="comment">...</div>
</div>
Controller:
[HttpPost]
//[ValidateAntiForgeryToken]
public async Task<PartialView> AjaxAddComment(string comment, /*...other params*/)
{
var newComment = ... // comment viewModel
// add comment to db
await db.SaveChangesAsync();
return PartialView("_CommentPartial", newComment);
}
_CommentPartial:
<div class="comment">
...
</div>
I'm fairly new to Angular and very new to using the ui-router, so I could be missing something obvious.
If I launch my results.html page on its own, everything from the Web API is bound correctly through the controller and shows up as expected.
When I start from index.html and click on the button that calls $state.go(), I am navigated to the results.html page .. but none of the data from the controller shows up. The controller & service are still being called though - because I put console.log() statements to verify that the object I want is being returned after $state.go() and it is - the template just isn't registering it.
Here is my code for my ui-router and main controller:
// script.js
var app = angular.module('BN', ['ui.router']);
// configure our routes
app.config(function ($locationProvider, $stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('');
$stateProvider
.state('default',{
url:'/',
templateURL:'index.html',
controller: 'MainController'
})
.state('results', {
url:'/results',
controller: 'ResultsController',
controllerAs: 'vm',
templateUrl: 'Results/Results.html'
})
.state('instructor', {
url:'/api/instructors/:id',
templateUrl: 'Instructors/Instructor.html'
});
$locationProvider.html5Mode(true);
});
app.controller('MainController', MainController);
function MainController ($state) {
var vm = this;
vm.Submit=function( ){
$state.go('results');
};
}
So Results.html renders perfectly fine launched on it's own, but when navigated to - the controller is called but not bound to the html template.
You have your index.html file set up properly, but after that you're using ui-router incorrectly.
In your index.html file where you have:
<body ui-view>
this tells ui-router to load the contents of your templates into the body of your document, so your templates should just be snippets of html to be rendered within your body tag. So you should delete everything from results.html until all that remains is this:
<div id="headerBar" >
<div class="form-group" id="headerBar" >
<input class="form-control input-lg" type="text" id="inputlg" placeholder="Zipcode" />
<button id="sub" class="btn btn-default btn-lg" type="submit" ng-click="vm.getInstructors()">Find an Instructor!</button>
</div>
</div>
<table>
<tr ng-repeat="Instructors in vm.instructors">
<td style="padding-top:5px;">
<div>
<nav class="navbar">
<div class="container-fluid">
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search" name="searchString" >
</div>
<button type="submit" class="btn btn-default" value="Filter">Search</button>
</form>
</div><!-- /.container-fluid -->
</nav>
</div>
</td>
</tr>
</table>
<div class="col-md-8">
</div>
<aside class="sidebar" ui-view="map">MAP</aside>
A few other things. You have the controller setup in your routes, so you don't need to specify it anywhere in results.html. Also you should not be able to navigate to results.html. Instead you would just navigate to (your domain)/results.
I have a main view that renders two partial views. The main view encompasses both of the partial views within a form. Each of the partial views also contain forms. All 3 views share the same viewmodel. What I want to do is encapsulate the data from all views with the main view, and run specific Controller action results with the partial views.
I want to know if this is even possible. When debugging I see that my content always posts to the HTTPPost of the Main views form. I have submit buttons for each of the forms accordingly. Sorry for the code post, its coming out all split up.
Main View:
#using (Html.BeginForm("Main", "Registration", FormMethod.Post,
new { #class="mainform" }))
{
<form>
<fieldset>
<div id ="option1" class="conglomerate">
#Html.Partial("_GetBusiness")
</div>
<div id ="option2" class="dealership">
#Html.Partial("_GetLocation")
</div>
<button type="submit" value="Create" class="buttonBlue" id="">
<span>Create a new dealer</span>
</button>
</fieldset>
</form>
Partial 1
#using (Html.BeginForm("CreateBusiness", "Business", FormMethod.Post,
new { #class="buisinessform" }))
{
<form>
<div class="editor-field">
#Html.DropDownListFor(m =>m.BusinessId, new SelectList(Model.Businesses,
"BusinessId", "BusinessName"), "")
</div>
<label>Your company not listed? Register yours below:</label>
<div class="editor-label">
#Html.LabelFor(model => model.BusinessName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.BusinessName)
#Html.ValidationMessageFor(model => model.BusinessName)
</div>
<button type="Button" value="" class="buttonBlue"id="TestSubmit">
<span>Add Dealer</span>
</button>
<div class ="confirm">
<button type="submit" value="Create" class="buttonBlue" id="">
<span>Click here to confirm dealer addition</span>
</button>
</div>
</form>
}
As Dave mentions, It is not valid HTML to nest forms. It's not just HTML5, but any version of HTML.
It might work in some browsers, in certain circumstances, but it is never valid. And you can never depend on what will happen even if it does seem to work. Your best course of action is to use multiple non-nested forms on a page.
Can you explain why you think you need nested forms?
No, you cannot have nested forms. Sorry.
See HTML5 guidelines
"Flow content, but with no form element descendants"
I am using a razor template so I can reduce the amount of clutter in my mvc views when working on code. I have created "section" which will render as the seperate pages required for my mobile pages as follows:
<div data-role="page" id="page2">
<div data-role="header">
#if (IsSectionDefined("Header2"))
{
#RenderSection("Header2")
}
else
{
}
</div>
<div data-role="content">
#if (IsSectionDefined("Content2"))
{
#RenderSection("Content2")
}
else
{
}
</div>
<div data-role="footer">
#if (IsSectionDefined("Footer2"))
{
#RenderSection("Footer2")
}
else
{
}
</div>
I use the same template as above for up to 3 pages.
My issue at the moment is I have assigned some code to my page 2 using:
#section Content2{
<div id="machinesearch" class="ui-content">
<ul id="machinelist" data-autodividers="true" data-theme="d" data-divider-theme="a"
data-filter="true" data-role="listview">
#foreach (var item in Model.Plants)
{
<li>#item.Asset_Descriptor<input id="Sap_ID" type="hidden" value="#item.Asset_SAP_ID"/></li>
}
</ul>
</div>
}
And my link to show this page is:
$("#testbutton").click(function(){
$('#page2').trigger('pagecreate');
$("#machinelist").listview('refresh');
alert("test");
});
But this does not seem to make any difference.
Any ideas?
I can see the data is all loaded in correctly when I view the html source of my first page which also contains the html for the second page. It seems to be because razor is injecting the data in to page 2 after the page 1 is loaded.
You aren't actually showing the page.....
$.mobile.changePage("#page2");
will show the page.