ASP.Net Core view as popupbox - c#

I am currently working on a form. In the form, if there is not an item needed you can click the add button and it takes you to a new form where you can add the item. Instead of my view going to another page, I want it to pop up above the form so that the user can just quickly add the item and not have to travel pages.
Here is a snipit from my Create.cshtml
<div class="form-group">
<label asp-for="INT_CertificationsID" class="col-md-2 control-label"></label>
<div class="col-md-3">
<select asp-for="INT_CertificationsID" class ="form-control" asp-items="ViewBag.INT_CertificationsID"></select>
</div>
<a class="btn btn-default" asp-area="" asp-controller="INT_Certifications" asp-action="Create">Add Certification</></a>
</div>
When the add certification attribute is clicked I would like a box to pop up to the Create.cshtml for the certification. So that they may quickly add it to the list and continue to fill out the form.
I have looked up several examples to do this but most of them are either too old, too long, or don't work in .netcore due to nuget package errors with JqueryUI.

You need to make a controller method that returns the page you want in the popup as a PartialView.
I think you mean modal and not "popup"... you need to use a modal mechanism to create a modal window and get (or post) your partial via AJAX and use the result to display in the modal window.
I like bootbox which is a wrapper for bootstraps modal functionality.

I would load partial view in a hidden div together with the pages that needs them and dynamically display them with JavaScript when needed. Don't use forms to send http request, instead use AJAX.
Using pop-ups can work against you because browsers comes by default with pop-up blockers. Might work on your devbox but it could have a completely different behaviour somewhere else.
Using forms to send request requires the page to be reloaded which does not provide a good user experience.
Fix your solution, don't use nugget for client side script. Use bower instead. Here's a link https://learn.microsoft.com/en-us/aspnet/core/client-side/

Related

Asp-Page-Handler not firing Method in Razor Model when Form Button is Clicked

First please know that I have googled and tried everything that I have found. I have been through solution after solution and read dozens of Stack Overflow questions before posting this. I have no idea why this is not working. That being said I am not super familiar with the Method Handler stuff so I might be making a stupid mistake.
Implementation Details
- .NET Core 2.2
- Microsoft.AspNetCore.Razor.Design 2.2.0
- AngularJS.Core 1.7.8
I am creating an internal portal to aggregate Jenkins build and test data. I want to allow a build of the job that runs Jenkins tests to be kicked off via a button on the page. When I click the button I don't get any errors. I get nothing in the console and don't hit any breakpoints that would be hit if it actually fired the OnPost method.
I have tried using the OnPost and OnPostAsync methods. I have tried using the custom name via the asp-page-handler as well as the default names. I have tried putting the asp-page-handler tag on the form and the button. I have tried using a button and an input. Nothing seems to change the behavior.
The Header of my Razor Page
#page "{handler?}"
#using JenkinsRazorApi.Pages
#using System.Linq;
#using System.Data;
#using System.Web;
#model FslModel
#{
ViewData["Title"] = "fsl";
}
My cshtml markup
<div>
<form method="POST">
<input type="submit" class="btnKickOffBuild" name="kickOffBuild" id="btnKickOffBuild" asp-page-handler="BuildClick" value="Build"/>
</form>
</div>
My method in my model (The PostToApi method is Async which is why I am using the Async version of OnPost)
public void OnPostBuildClickAsync()
{
apiClientCalls.PostToApi("FslSmokeTest", "BuildKickOff");
}
My OnGetAsync method fires when the page loads without issue. Everything that happens in that method works. I am able to reference the Model in the normal Razor fashion so the model is accessible and tied to the page. I just can't get the OnPost method in my Model to fire when I click the btnKickOffBuild button.
If someone could please point me in the right direction I would really appreciate it.
*************EDIT**********************
I tried making the OnPostBuildClickAsync method actually Async and I tried it how I have it above and took the Async off the method name to no avail.
I also tried, as a test, turning all of the Anti-Forgery stuff that is tied to the Razor framework off globally just to rule that out. That didn't work either.
I tried doing this a completely different way by adding the method to my Angular scope wrapped in a javascript function that should only fire if the button is clicked but since it is a server side # tag it runs on page load regardless of the condition in the function.
*************EDIT**********************
This boils down to an Angular thing.
As per the "Submitting a form and preventing the default action" section in the following Link:
https://docs.angularjs.org/api/ng/directive/form
Angular requires an action tag to submit the form to the server. Without it the form is prevented from submitting. I altered my cshtml to:
<div>
<h5 style="margin-left: 50px; float:left;">Test Pass/Fail</h5>
<form method="post" action="">
<button type="submit" class="btnKickOffBuild" asp-page-handler="BuildClick">Build</button>
</form>
</div>
Of particular note is the action="". This forces Angular not to block the submission of the form to the server.
The following question has some detail around Angular Actions also:
ng-action does not add action attribute in the form
Edited:
I have found the root cause of it. You need to create a Razor ViewImport file and import all the razor dependencies in that file. That ways you can use the taghelpers in the application

Send Ajax Requests vs Sending Entire Form By Id

The client should be able to send everything with a button, so I can do the following:
Send everything as form fields named like invoiceId_detail_text where invoiceId would be the id of the invoice, detail the part, and text the kind of field.
Example:
<form id="invoices" name="invoice">
#foreach(var Invoce in Model.Invoices) {
<div>
<input type="number" id="#String.Format("{0}_amount", Invoice.InvoiceId)"/>
</div>
/*More Input Fields for the Invoice*/
<div>
<button type="submit"></button>
</div>
}
</form>
Or I can put every invoice separated in its own form, and send them by ajax, every form success I send the next one and so on.
Example:
#foreach(var Invoice in Model.Invoices) {
string formName = String.Format("{0}_form", Invoce.InvoceId);
<form id="#formName" class="invoiceForm" id="#formName" action="#Url.Action("EditIndividualInvoice","InvoicingEdit")">
<input type="hidden" name="InvoiceId" value="#Invoice.InvoiceId"/>
<div>
<input type="number"/>
</div>
/*More Input Fields for the Invoice*/
</form>
}
<button type="button" onclick="SendAllForms();">Send</button>
I did some research between some of my co-workers and many of them told me to just go with a post with all the invoices at the same time and then access every field by item id because I don't have knowledge of how many invoices are going to be sent, but i can get all of them by class on JQuery so it shouldn't be a problem.
I also read this article from a UX point of view and it keeps me thinking about it.
By doing it with AJAX the cliend could be able to see a loading bar and it would be great, but if he closes the page the request would be incomplete and it could be complicated.
Which option could be better and why and what are the security implications of using one over another?
I think the solution depends principally of the behavior that you wish.
By doing it with AJAX the cliend could be able to see a loading bar and it would be great, but if he closes the page the request would be incomplete and it could be complicated.
In the 2 solutions, if the user closes the page after clicking the button, this will not cancel the save. Once the request sent, it cannot be cancelled. So you shouldn't have "security" problems whatever the choosen solution.
The only thing you need to be careful, is to disable all AJAX buttons during an AJAX request, to avoid the user sending several request in the same time (that can provoke saving inconsistency data).
The classic solution is generally most simple to implement.
The AJAX solution can be most complicated to implement (more code), but provides a friendliest behavior.

ASP.NET MVC 5 - "Create" view that can handle any number of elements for an IEnumerable based on clicking an "Add row" button?

I am writing a recipe manager for my wife in C#/.NET MVC 5. I'm getting to the page for creating a recipe, and I'm a little stumped. A recipe consists of a Name and a list of ingredients.
When I create a view, I have my form:
#using(Html.BeginForm()){
//Form elements
#Html.DisplayNameFor(x => Model.Name)
//button for adding a new ingredient to the recipe
<input type="submit" text="Submit New Recipe!" />
}
When the button for adding an ingredient is clicked, it should render a block of html inside the form just above the button itself, that way the user can add any number of ingredients and then submit the recipe back when the form is posted back to the controller.
For this functionality, should I make the button call a controller that sends back a partial view or something? I'm not sure how to accomplish this outside of JavaScript, but I'm wanting to use a .NET MVC solution if I can.
I try to minimize my reliance on javascript whenever I can, however I agree with #br4d that knockout is your best option here. If you want to avoid it at all cost, it will be more complex, slower and not as user friendly but here is how I would do it.
Enclose the form in a div. Have a place holder div inside the form to hold your ingredients list. Make the "Add new ingredient" call into a controller that will return a partial view with the required fields. In the target attribute indicate the place holder div as the update target and append the response to the html of the place holder div by specifying InsertionMode.InsertAfter.
<div id="parentDiv">
#Html.BeginForm........
#Ajax.ActionLink("Add New Ingredient","ActionName","ControllerName",routeValues,
new AjaxOptions
{
UpdateTargetId = "ChildDiv",
InsertionMode = InsertionMode.InsertAfter
}
<div id=ChildDiv>
</div>
</div>
This code is by no means comprehensive or production ready (I prefer to have a way of handling failed ajax calls and you might want to block off interactions until the call comes back just to mention two of the enhancements). Once again KnockOut would be the preferred way to do this.

Open a new window with Same session using jquery/C# Razor

I am trying to open a new window with same session as the current one. I wrote some code below but its no luck yet.
For example lets say i have a form with a label (Name), textbox (where the text goes in)
and a button when pressed takes me to a new window.
If i press the button it should open a new window with the same form elements and text in the textbox if it was put in before.
Also please note the new window must be opened as a new tab in the browser with the same state and same elements as in the previous browsers.
Anyone got an idea on this (using razor view engine or jquery/javascript) ? Thanks in advance.
<label for="Name">Name</label>
<input type="textbox" value="nothing" id="text" />
<input type="button" value="press me" id="submitButton" />
$(document).ready(function()
{
$('#submitButton').click(function()
{
var currentUrl=document.URL;
window.open(currentUrl,"newWindow",300);
event.preventDefault();
});
});
You may be able to accomplish this by using modals instead of popup windows. Jquery UI has built in modal support: http://jqueryui.com/dialog/
The advantage to this approach is that no data needs to be passed into a separate page. Your modal code would look something like this, with jQuery Dialog. This would go on the same page as your initial inputs:
<div id="dialog" title="Basic dialog">
<input type="text" id="popupText" name="popupText" />
</div>
and your click event would modified update the modal input and show the modal:
$(document).ready(function(event)
{
$('#submitButton').click(function()
{
$("#popupText").val($("#text").val());
$("#dialog").dialog();
event.preventDefault();
});
});
This could definitely be cleaned up but I believe it'll do what you need pretty simply. The dialog can contain any html elements, so you can add a separate form if necessary.

jQuery not executing because of asp:Panel

I am using the jQuery plug in contentcarousel. It is a good plugin and all but I need the ability to dynamically create a certain number divs according to the user.
To achieve this I am using an <asp:panel> and then running a Literal & foreach in C# to populate the panel. The problem comes in when the <asp:panel> is used.
It seems as if the jQuery plugin can only work if the divs occur in a certain order.
ie.
<div id="ca-container" class="ca-container">
<div class="cawrapper">
<div class="ca-item ca-item-2">
<div class="ca-item-main">
When the panel is used, then the order becomes
<div id="ca-container" class="ca-container">
<div class="cawrapper">
<div id="panelinfo">
<div class="ca-item ca-item-2">
<div class="ca-item-main">
And the plugin stops working. At least I am assuming so due to the fact that the arrows dont show up, none of the buttons work, etc.
Does anyone know if there is a way around this? Maybe a way to "hide" the div that the panel becomes?
It sounds like you want to have a control that acts like a Panel in server side code, but instead of being rendered as a div just plops all of whatever would have been inside of it without adding anything "extra". That's pretty much the definition of an asp:Placeholder. Just use that instead of a Panel.
Try moving your JQuery code into window.load. I'm assuming you have your jquery in document.ready which will fire the second the dom is ready.
$(window).load(function(){/*Your code*/}

Categories

Resources