How to implement printing in ASP.Net MVC3 - c#

As part of my current task in a given list of items, user can select some of them and invoke 'Print' no the selected items.
For each selected item we need to print the details. It is similar to printing invoices of selected items in a sales system.
I have created a partial view to write each record details but I am not sure how to use it as per my requirement.
Can I call jQuery print on document.ready to achieve my requirement?
As #Levib suggested, calling partial view in my PrintView. And PrintView's document.reay function is calling window.print. But when I try to invoke 'Print', I can not see print dialogue.
This is my view,
#section Styles
{
<link rel="stylesheet" href="AdminStyle.css" type="text/css" media="all" />
<link rel="stylesheet" href="AdminPrintOrder.css" type="text/css" media="print" />
}
#foreach (var item in Model)
{
<div id="content" style="page-break-before: always">
#{Html.RenderPartial("_OrderDetailView", item);}
</div>
}
#section scripts
{
<script type="text/javascript">
$(document).ready(function () {
debugger;
window.print();
});
</script>
}
And my print invoker view is
function printInvoices(){
$.ajax({
type: 'POST',
url: '/Batch/PrintInvoices',
data: '{ "allocationId" : "' + unSelected.toString() + '"}',
contentType: "application/json; charset=utf-8",
traditional: true,
success: printedView,
error: errorInSubscribing
});
}
Do I need to handle ajax reposne to populate print dialogue.
function printedView() {
unSelected = [];
}
And controller action is
[HttpPost]
public ActionResult PrintInvoices(string allocationId)
{
var context = new BatchContext();
var orderDetails = context.GetOrderDetails(RetriveList(allocationId));
return View(orderDetails);
}

Define a print stylesheet for your page. You do this by using the #media print declaration.
What you can then do is wrap each partial view on the page that you are going to print in a div and apply the 'page-break-before: always' CSS attribute to it.
This will ensure that each partial view ends up on a different page. Call 'window.print()' on the page load and you're done!
Given the extensive questions posed in the comments for this answer, here is a more detailed description of what needs to be done:
Preparation
A stylesheet needs to be defined and applied to the page which defines what the page will look like when printed.
This can either be done by using a #media print { } declaration in an existing stylesheet, or by applying the media="print" attribute to the link tag in your page which includes the stylesheet. You appear to have done this correctly.
This stylesheet must include a page-break-before: always declaration for all elements before which you would like there to be a page break. You seem to have done this with inline styles. Personally I would have rather done this in the print stylesheet than as an inline style. This step is integral to you being able to print one item per page.
Printing
window.print() allows you as the page author to define when the page is printed. This does the same thing as CTRL + P or as clicking the print button, except you can do it from your JavaScript.
Ajax has nothing intrinsically to do with printing. Ajax is a means to asynchronously make HTTP calls from your page without changing or reloading it and updating your page as a result. If you wanted to dynamically populate your page with items to print based on user input, then you could very well do so with Ajax. If you merely want to print the page, then you don't need to use Ajax.
the navigator.**
Two important points:
window.print() prints the page that is currently onscreen. If you want to print a different page, you need to load the other page in some way shape or form (perhaps through a popup) and call window.print() on that page.
The print stylesheet defines what the printed page will look like in contrast to the onscreen version. This means that you can have a page of items and lots of other stuff, and print only the items when the user clicks the print button. You would do this by setting the display: none property in your print stylesheet on all the elements that you do not want to appear on the printed page.
About PDFs:
I have nothing against exporting pages to PDF when necessary, but as you did not specifically ask about a PDF solution, I have given you the HTML+CSS solution to your question. PDFs also take a minute to generate and load. They are great, however, when your users will want to save copies of what they are printing. If this is the case for your site I strongly recommend that you consider such a solution.
Testing:
How do you test a print stylesheet? The easiest way is to simply click the print button in Chrome which will show you a lovely preview of what your site is going to look like when it is printed.
Final word:
For now, forget about window.print() and just focus on getting your page looking like it should by applying the appropriate CSS. Write your CSS, run your page, look at the output in Chrome, modify your print stylesheet as needed... Rinse and repeat. Only once you have the page appear exactly as you want it when clicking the print button should you then look at calling the print function automatically in your JavaScript.

How I do printing in MVC:
Create a view with exactly what you want to print layed out how you want it to look
Use the Rotativa library to turn your MVC View in a pdf document.
Simple as changing your Action to look like this
public ActionResult PrintInvoice(int invoiceId)
{
return new ActionAsPdf(
"Invoice",
new { invoiceId= invoiceId })
{ FileName = "Invoice.pdf" };
}
I believe it will obey the css page-break, so if you need to only print one item per page you can use that markup to force items to new pages.

I will create a PDF to better control the layout of the page.
With jQuery I will get the selected items from the user than make an ajax call, or a simple POST, to an action method that accept a list of your items as parameter and then return a filestream containing your pdf.
There are a lot of libraries free and commercial to create a pdf both at runtime or at design time.
I personally use DevExpress and I'm happy with it.
As an opensource alternative you can consider PDFSharp

Related

Submit button does not trigger on items added via ajax

I have an mvc view that contains a list of items. Each item is displayed using a partial view. The user can edit, add, and delete items in the list. All of this works.
However, if the user adds an item, the item cannot be edited until the page is refreshed. When the user selects the submit button, the post does not occur. There is no network activity shown in Chrome dev tools - nothing happens.
The output html is the same for items that are included in the initial page load and items added via ajax.
<form action="/booking/UpdateRoomFlow" data-ajax="true" data-ajax-method="POST" data-ajax-success="update_27365547" id="roomflowform_27365547" method="post" novalidate="novalidate"></form>
I noticed that when I inspect element in chrome, the form does not wrap the form fields, but when I look at view source, it does.
I've tried useing Ajax.BeginForm and I've tried writting the html out myself, with the same results either way.
This is the Ajax.BeginForm...
#using (Ajax.BeginForm(
"UpdateRoomFlow",null,
new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = targetfunction
},
new { #id = #formid, #novalidate = "novalidate"}))
{
Any ideas?
EDIT: Something to note - this form is placed inside a tr tag above a td tag, which could cause an issue as that is invalid markup - however, its working in all cases except items added via ajax call.
<script> tags included in an HTML AJAX reponse are stripped, and since Ajax.BeginForm adds script tags to the HTML to enable it's functionality, you essentially end up with a regular old form that does nothing. There's nothing you can do about this, as the browsers strip <script> tags for security reasons. Your only recourse is to stop using Ajax.BeginForm and write your own JS to handle the AJAX submit, which you can then include in the main view or an external file which will not be affected, which is not a bad idea anyways. The Ajax.* family of helpers are awful just for reasons like this.

How do I fire a aspx script when a dynamically added button is clicked?

Here is the context:
I am building a .aspx page that allows the user to administrate some xml documents we have on our server. The page content is loaded using AJAX, so buttons and forms are dynamically added to the document.
If I had static buttons that I was creating within the .aspx page before it loads on the client's machine, I could attach an event to it very easily. However, I'm dynamically adding and removing buttons and forms on the fly, using jQuery.
Here is a simplified example:
In the following jsFiddle, I'm pretending that the html document contains the following script:
<script language="C#" type="text/C#" runat="server">
void SaveAllChanges(Object sender, EventArgs e)
{
Button clickedButton = (Button)sender;
clickedButton.Text = "foobar";
}
</script>
And that I have a javascript file that contains the following:
$('button.buttonGenerator').click(function() {
$('.buttonContainer').append(
'<button onclick="SaveAllChanges">' +
'Save All Changes!' +
'</button>'
);
});
Obviously the buttons I am creating can not run the function SaveAllChanges with the way it is now. I added the onclick attribute to show what I needed to happen, in a pseudo-code kind of style.
How can I make it so that dynamically added buttons can run the C# method I have defined within the script tag at the top of the document?
Here is the jsfiddle: http://jsfiddle.net/2XwRJ/
Thanks.
You can give all buttons that must save changes a common class (e.g. class="ajaxButton") and have one jQuery method that responds to click events on elements matching that class (use live so that updates to the DOM are reflected).
$("button.ajaxButton").live("click", function(){
// Perform your Ajax callback to run server-side code
});
What you need to do is use something like ..
$(document).ready(function() {
$('button.buttonGenerator').click(function() {
$('.buttonContainer').append(
'<button id="#dynamicCommentButton" onclick="SaveAllChanges">' +
'Save All Changes!' +
'</button>'
);
});
$(document).on('click', '#dynamicCommentButton', function() {
alert($(this).attr('id'));
});
});
You are not going to be able to add the buttons like you have it there as this code here is just adding it as an HTML DOM element and the onclick attribute will be the on the client element. As a result clicking the button will try fire a SaveAllChanges javascript function
$('.buttonContainer').append(
'<button onclick="SaveAllChanges">' +
'Save All Changes!' +
'</button>'
);
What would be best would be to create that SaveAllChanges function in javascript and then you can handle it from there. Two of the ways I see you being able to do this are:
Have a http endpoint setup (script service, web api or just posting to a page) that you call using Ajax from your javascript. You can then pass through any needed arguments.
You could have a hidden element and hidden button on the page so that when the javascript is called it populates any arguments you need and then clicks the hidden button and posts the page back.
Personally I would choose the first approach from a user experience stand point as the page will not be posting back each time. I have used something similar to the second approach and it works fine but just feels very clunky.

HTML helpers in ASP.NET MVC 3 with Javascsript action

I have many HTML helper in Helpers.cshtml file, but some of the helper (html) need some jquery action, so how do i can call jquery inside helpers.cshtml, is that possible?
i know we can keep the js file in header or particular page, but i do not want to do like that, i want to use jquery or javascript only on the page which loaded particular helper.
anyone have idea on this?
My scenario is, i have list box control, that is properly loading from helper, but i need to apply custom theme to the list box.
Little more Clarity
//in index.cshtml
#Helpers.testListBox("mylist" "1,2,3,4,5,6,7")
//in Helpers.cshtml
#helper testListBox(string listName, string listData){
//...... HTML code .........
//Javascript here?
}
With Web Forms, the framework could automatically include Javascript (once) when certain server controls were used on a page; ASP.Net MVC has no such facility. It sounds like this is what you're missing.
The way to do it is on the client. Look at RequireJS at http://requirejs.org/. This is a client-side library for managing Javascript dependencies. This does what Web Forms did, but better, and it does more. Your master layout will have a script tag like this:
<script src="/Scripts/require.js" type="text/javascript" data-main="/Scripts/main"></script>
This can be the only script tag you include on every page. Everything else can be dynamically loaded only as needed by RequireJS. It's true that you load this on every page, but it's smaller than jQuery, and it earns its place because it does so much for you.
Using your example, let's say you have this markup:
#Helpers.testListBox("mylist" "1,2,3,4,5,6,7")
and it renders HTML and needs jQuery scripting. You would render this:
// HTML for list box here
<script type="text/javascript>
require(['jquery'], function($) {
// Do your jQuery coding here:
$("myList").doSomething().whatever();
});
</script>
The require function will load jQuery, unless it has already been loaded, and then execute your code. It's true that your jQuery snippet is repeated once per use of the HTML helper, but that's not a big deal; that code should be short.
RequireJS manages dependencies effectively; you can have module A, and module B which dependes on A, and module C which depends on B. When your client code asks for module C, A and B will be loaded along with C, and in the correct order, and only once each. Furthermore, except for the initial load of require.js, scripts are loaded asynchronously, so your page rendering is not delayed by script loading.
When it's time to deploy your site on the web server, there's a tool that will examine the dependencies among the Javascript files and combine them into one or a small number of files, and then minimize them. None of your markup has to change at all. While in development, you can work with lots of small, modular Javascript files for easy debugging, and when you deploy, they are combined and minimized for efficiency.
This is much better than what the web forms framework did, and entirely client-side, which in my opinion is where it belongs.
You can put a <script> tag in the helper body.
How about this for an example of a partial view:
#model Member.CurrentMemberModel
#{
var title = "Test View";
}
<script type="text/javascript">
// Javascript goes in here, you can even add properties using "#" symbol
$(document).ready(function () {
//Do Jquery stuff here
});
</script>
#if (currentMember != null)
{
<div>Hello Member</div>
}
else
{
<div>You are not logged in</div>
}

How can i print a page in asp.net without master page and to change color schemes of the page?

i have made a page in asp.net, i have a costing calculator which has more than 50 fields, dependent on each other, one is the result of previous two and like that, i want my page to be printed in a well manner, and the header of the page which is in master page should not be in print, also the color schemes i want to adjust, let me know the best solution for this which .net provides
Put the content inside <div id="divid">YOUR CONTENT NEEDS TO BE PRINTED</div>
Then call the javascript function on button click which will print the selected area or only html of div. pass the id of div on calling javascript function.
function CallPrint(var strid)
{
var prtContent = document.getElementById(strid);
var WinPrint = window.open('','','letf=10,top=10,width="450",height="250",toolbar=1,scrollbars=1,status=0');
WinPrint.document.write("<html><head><LINK rel=\"stylesheet\" type\"text/css\" href=\"css/print.css\" media=\"print\"><LINK rel=\"stylesheet\" type\"text/css\" href=\"css/print.css\" media=\"screen\"></head><body>");
WinPrint.document.write(prtContent.innerHTML);
WinPrint.document.write("</body></html>");
WinPrint.document.close();
WinPrint.focus();
WinPrint.print();
WinPrint.close();
return false;
}
Call CallPrint('DivGrid');" on onclick() of button or use below: but.Attributes.Add("OnClick", "return CallPrint('DivGrid');");
Nothing to do with .Net and everything to do with a print stylesheet. You can create a stylesheet which will only work for when the page is printed. And you can change everything from what displays to postion to colours.
Use:
<LINK rel="stylesheet" type"text/css" href="print.css" media="print">
Note media="print" means it'll be used for printed pages.
I know that question has been asked a long time ago, however there is no accepted suggestion. So here my approach for friendly print version when using Master page.
Create an empty master page (PrintVersion.Master) to serv as print version. Add what ever you need to be print (like logos) if anything to that master page.
from your content page, add a print link with target blank. Make the href to load the current page. From the href add a querystring so you can capture it from your content page preinit event.
From your content page preinit event detect if the querystring to print exists, then specify the blank master page like: MasterPageFile = "~/Ful/Path/of/your/PrintVersion.Master"
Optional, on the PrintVersion.Master on document.ready call: window.print(); The browser print dialog will automatically open.
You can make a new printable page version, which doesn't include a header. This version can also have the layout you need.

how to print the content of a label or panel in asp.net?

I have a label control in a page in asp.net 2.0 and a button Print.
Clicking on print button I need to print the content of the label and I need same for a panel also.
Is it possible to implement this?
If yes then how to implement that?
Please help.
What about Window.Print() method? Because execcommand method will not work other browsers that IE. Use CSS media option to control the print area.
You would need to add some client side javascript to your Print button to execute the brower's print command. The javascript below could be used to print the whole document page and would be a good place to start. Note: It isn't possible to do this without displaying the print dialog unless you use a third party component.
// Print Page
window.print();
If you wanted just to print certain sections of your page you can achieve this two ways. Firstly, you could render the content to be printed into a hidden iframe and then print just that frame. You would do this using the same code as above only from within the frame itself.
Secondly, you could use a media style print style sheet, a CSS that applies only when printing. Inside this sheet you would set the styles you wanted to print as normal and the styles you didn't want to print to "display:none". The link below contains more information on print stylesheets.
http://www.webcredible.co.uk/user-friendly-resources/css/print-stylesheet.shtml
One more approach could be to open new window and populate the contents of div you wanted to print and have print link/button on that page.
Ex:
var win = window.open(...)
win.document.body.appendChild(document.getElementById('divToPrintId'))
This is how the code will look like this approach is used to print the content/part of the page.
Use below code in button onclick event
ClientScript.RegisterStartupScript(this.GetType(), "PrintOperation", "PrintGridData()", true);
Above link will call function named PrintGridData() which is written in head section as below
<script type="text/javascript">
function PrintGridData()
{
var prtGrid = document.getElementById('<%=GridView.ClientID %>');
prtGrid.border = 0;
var prtwin = window.open('', 'PrintGridViewData', 'left=100,top=100,width=1000,height=1000,tollbar=0,scrollbars=1, status=0,resizable=1');
prtwin.document.write(prtGrid.outerHTML);
prtwin.document.close();
prtwin.focus();
prtwin.print();
prtwin.close();
}
</script>
in this script it will only print div name GridView and other part will not be printed

Categories

Resources