Blazor | if there's any method to convert the Razor Pages to HTML - html

I'm using Blazor Sever to make a website.
And there's a need that i should convert my razor page to htmlpage.So taht i can use my HTMLtoPDF interface to let customers to download their project.DO you have any ideas?
Such as the following Razor page.There're many variables and custom components in this page,how can i convert it to a static HTML page? Thanks a lot !!!
<div id="ABS" class="text-left">
<table style="border:black solid;font-weight:bold;font-size:12px" width="1200" cellspacing="0" cellpadding="0" border="1">
<tr class="text-center" style="background-color: #99CCFF">
<td width="300">描述 <br> Description </td>
<td width="500">标准选项 <br> Standard Option</td>
<td width="400">备注 <br> Comments</td>
</tr>
<ABS_HU ABSTI_HU="#ABSTI.HU" IsExpended="#IsExpendAll" />
<ABS_WSS ABSTI_WSS="#ABSTI.WSS" IsExpended="#IsExpendAll" />
<ABS_SYSTEM ABSTI_System="#ABSTI.System" IsExpended="#IsExpendAll" />
<tr>
<td style="background-color: #CCFFFF" width="300" class="text-center">
</td>
<td width="500" class="text-center">
</td>
<td style="background-color: #CCFFFF" width="400">
</td>
</tr>
</table>
</div>

I assume the customer sees the report first and then click a button like "save."
The general idea is to let the client (browser) render your component, send the "raw HTML" back to the server, and then you can use your HTMLtoPDF.
Let's create the javascript function. Maybe there are ways to do it with vanilla js as well. You could add these lines to your _Host.cshtml file.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></script>
<script type="text/javascript">
window.copyHtml = function () {
return $("html").html();
};
</script>
In your Blazor component, inject IJSRuntime and call the method when the button is clicked.
#inject IJSRuntime js
#* all the other components here *#
<button class="btn btn-primary" #onclick="GenerateHtml">Save Report</button>
#code {
private async Task GenerateHtml()
{
String result = await js.InvokeAsync<String>("copyHtml", Array.Empty<Object>());
//in a wasm project, use HttpClient to send the data to the API
//as a "proof," it is sent back to the server
Console.WriteLine(result);
//send to HTMLtoPDF
}
}
In case the saving should be done without clicking a button, the Blazor component lifecycle can help. In the lifecycle of a component, when the rendering is finished, the method OnAfterRenderAsync is executed. So, you can override it and generate the HTML there.
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if(firstRender == true)
{
await GenerateHtml();
}
}

Related

HTML validation not working for input field loaded using Jquery

I have a form input field loaded by jquery based on user selection but the HTML form validation and even jquery form validation not working for the input field loaded by jquery.
<tr>
<td colspan="2">
<select name="usdtnetwork" required="required" id="usdtnetwork" onChange="getaddressForm()" title="Please select your USDT Network">
<option>::: Choose your USDT Network :::</option>
<option value="ERC20">ERC20 (ETH)</option>
<option value="TRC20">TRC20 (TRON)</option>
<option value="BEP20">BEP20 (BNB)</option>
</select>
</td>
</tr>
<tr>
<td colspan="2">
<div align="left">
<span id="showinputfield"></span>
</div>
</td>
</tr>
This is my jquery (Noticed I tried e.preventDefault() but can't figure what am doing wrong so I commented it out)
<script>
/*$('.thisbuyUSDT').click(function (e) {
var myForm = jQuery( "#catalog_formusdt" );
// html 5 is doing the form validation for us,
// so no need here (but backend will need to still for security)
if ( ! myForm[0].checkValidity() )
{
// bonk! failed to validate, so return true which lets the
// browser show native validation messages to the user
return true;
}
e.preventDefault(); */
function getaddressForm() {
//e.preventDefault();
$("#loaderIcon").show();
jQuery.ajax({
url: "usdt_form_field.php",
data:'usdtnetwork='+$("#usdtnetwork").val(),
type: "POST",
success:function(data){
$("#showinputfield").html(data);
$("#loaderIcon").hide();
},
error:function (){}
});
}
//}
</script>
you have to reset validation on form after add some element (after $("#showinputfield").html(data);) by :
myForm.removeData("validator").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(myForm );
if it doesn't work please share complete html and jquery code

How to Pass JSON Object value From HTML Onclick function to JavaScript ? MVC

I am working on MVC trying to pass id on click button from HTML to JS my code where i am creating table in HTML is,
<tbody>
<tr ng-repeat="Survey in vm.AllSurveys">
<td>{{Survey.visitNumber}} </td>
<td>{{Survey.id}}</td>
<td>
<button id="myButton" onclick="myFunction('{{Survey.id}}');">Home</button>
</td>
</tr>
</tbody>
On click function is like,
function myFunction(id) {
console.log(id);
location.href = "http://localhost/Test?visitId="+id;
}
I have data in this format,
[{VisitNumber: "Visit_U_1", id: "107"},... So on]
But i got this error in html onclick line,
Error: [$compile:nodomevents] http://errors.angularjs.org/1.3.9/$compile/nodomevents
at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:6:416
at pre
<button id="myButton" onclick="myFunction('{{Survey.id}}');">
I tried solutions but did not get success
Hopes for your suggestions
You can use ng-click directive to pass data like below code
<button id="myButton" ng-click="myFunction(Survey.id);">Home</button>

Passing innerHtml value as parameter for play framework routes

hello i am trying to pass inline edited table value as a parameter to play routes can someone help me with the same
here is my html code
<table class="gradienttable">
<thead>
<tr>
<th>Task</th>
<th>TimeSheetdate</th>
<th>Hours</th>
<th>IsBilled</th>
<th>Work Place</th>
</tr>
</thead>
<tbody>
#for(element <- CurrentPage) {
<tr>
<td contenteditable="true" id="task1">#element.getTask()</td>
<td>#element.getTimeSheetDate()</td>
<td contenteditable="true" id="hours">#element.getHours()</td>
<td contenteditable="true" id="isbilled">#element.getIsBilled()</td>
<td contenteditable="true"id="workplace">#element.getWorkPlace()</td>
<td>
</tr>
}
</tbody>
</table>
routes
GET /Application/edit controllers.Application.edit(task1:String)
application.java
public static Result edit(String task1)
{
return ok(DisplayTimeSheet.render(task1));
}
It looks like you're confusing the server-side rendered Scala template with the DOM actions of the client. For #{routes.Application.edit(task1.innerHTML)}, task1 doesn't exist as far as the non-DOM template is concerned.
Your use of <a href="..."> is kind of weird, because that would make a synchronous call and if you're into inline editing then maybe that's not what you want. This answer covers an asynchronous approach using Play's JavaScript router support (which, if you haven't seen it before, is very cool).
You'll need to expose edit in the JavaScript router:
// You can also return an F.Promise<Result>
public static Result jsRoutes() {
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter("appRoutes", //appRoutes will be the JS object available in our view
routes.javascript.Application.edit()));
}
And then expose that method in the routes:
GET /assets/js/routes controllers.Application.jsRoutes()
That will generate a chunk of JavaScript that you can import
<script src="#controllers.routes.Application.jsRoutes()" type="text/javascript"></script>
And finally, write some JavaScript to handle the inline editing completion.
function doInlineEdit(taskName) {
appRoutes.controllers.Application.edit(taskName).ajax( {
success : function ( data ) {
target.closest('li').remove();
}
});
}
Then you just need to wire that method to be called when your inline-editable element changes content.
You can find additional info here.

HTML form validation in Apps Script

I am very new to coding and have managed (with some help from friends) to create a form that geo-locates the submitter and writes the values (+coordinate) to a Google Sheet. Where I am having trouble is in the HTML5 REGEX and required validations.
When I click the submit button the REGEX and required validation pop-up windows kick in but unfortunately at the same time, the form data is submitted to the Google Sheet and the data is cleared from the form.
I cannot figure out how to make the validation happen first, and then proceed with the submission instead of both happening simultaneously.
Thank you in advance for your help!
code.gs:
function doGet() {
var html = HtmlService.createTemplateFromFile("test").evaluate()
.setTitle('Engagement Card')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
return html;
}
function addData(data){
var ss = SpreadsheetApp.openById('1g*********************OnE').getSheetByName('Sheet1');
ss.appendRow(data);
}
test.html
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
</head>
<body>
<div id="formdiv">
<table width="500">
<tr>
<td align=center>
<img src="https://lh5.googleusercontent.com/5PX_VkGEwpy6YfE9mOBP3tSZ-PE6QW_J2AIIGRYtKuA=w231-h207-p-no" alt="" width='200' />
</td>
<td colspan=2 align=center>
<font size=7>Virtual<br><br>Engagement<br><br>Card *Beta*</font>
</td>
</tr>
</table>
<table width="500">
<tr>
<td colspan=3 align=center>
<font size=3>Please complete the information below</font>
</td>
</tr>
</table>
<form id="form">
<table width="500">
<tr>
<td>First Name:</td>
<td><input type="text" pattern="^[A-Z]+[a-zA-Z]*$" id="first" placeholder="Please type your first name" title="Name must start with a capital letter and not contain punctuation or spaces" required="required" /></td>
</tr>
<tr>
<td colspan=2 align=center><button type="submit" class="action" id="submit">Submit</button></td>
</tr>
</table>
</form>
</div>
<script>
$('#submit').click(function getLocation() {//when the submit button is clicked run this function (getLocation)
if (navigator.geolocation) {//if the browser supports geolocation then...
navigator.geolocation.getCurrentPosition(getData);//get the current position and pass the values to function getData
} else {//if the browser does not support geolocation then...
$('#formdiv').append("Geolocation is not supported by this browser.");//append this message in the web interface
}
});
function getData(position) {//starts the getData function and names data passed to it by getLocation as "position"
console.log(position);//logs the data passed by getLocation in the JS log for viewing
console.log('Running getData');//logs the words "Running getData" in the JS log
var latitude = position.coords.latitude;//assigns the latitude value from geolocation to var latitude
var longitude = position.coords.longitude;//assigns the longitude value from geolocation to var longitude
var coords = [latitude, longitude];//combines latitude and longitude into an array named var coords
var data1 = $('#first').val();//gets the values from the inputs using the input id
var data = [data1,latitude,longitude];//combines data elements in an array named var data
console.log(data);//logs the data values in the JS log for viewing
google.script.run.addData(data);//runs the function in the code.gs file
console.log('Data transmitted');//logs the words "Data transmitted" in the JS log
var field1= document.getElementById('first');
field1.value= field1.defaultValue;
};
</script>
UPDATE 20DEC 1430EST: I changed getLocation to run on submit (vs. on click) using #user9090's advice and added some console logs. Changing to .submit allows the validation and required fields to do their job which is what I was looking for. However, now the script stops in getLocation. "browser supports geolocation" gets logged in the console but then the screen goes white. I believe that getData is not being ran anymore. Any ideas?
$('#form').submit(function getLocation() {//when the submit button is clicked run this function (getLocation)
console.log('getting location');
if (navigator.geolocation) {//if the browser supports geolocation then...
console.log('browser supports geolocation');
navigator.geolocation.getCurrentPosition(getData);//get the current position and pass the values to function getData
} else {//if the browser does not support geolocation then...
console.log('browser does not support geolocation');
$('#formdiv').append("Geolocation is not supported by this browser.");//append this message in the web interface
}
});
function getData(position) {//starts the getData function and names data passed to it by getLocation as "position"
console.log(position);//logs the data passed by getLocation in the JS log for viewing
console.log('Running getData');//logs the words "Running getData" in the JS log
Update 20DEC 1620EST: Turns out, the script works fine now, and validates. My last comment is only true is there is a validation error. If I complete the form abiding by the regex and required elements, the data submits just fine. Although, if I have a validation error, the script hangs in getLocation after the error is corrected and the submit button is pressed again...
Change first 7 lines inside your script block (in test.html) with following lines of code,
$("#form").submit(function(event) {
console.log("Submitting form....");
google.script.run.withSuccessHandler(function(e){
// Do you validation here
}).addData(this); // this is a form's data passed to your GAS function
});

Using HTML5, how do I use contenteditable fields in a form submission?

So I have a bunch of paragraph elements which are dynamically populated from a db. I have made the elements contenteditable. I now want to submit edits back the the db via a standard form submission. Is there a way to post the contenteditable elements back?
You have to use javascript one way or the other, it won't work as a "standard" form element as it would with a textarea or the like. If you like, you could make a hidden textarea within your form, and in the form's onsubmit function copy the innerHTML of the contenteditable to the textarea's value. Alternatively you could use ajax/xmlHttpRqeuest to submit the stuff a bit more manually.
function copyContent () {
document.getElementById("hiddenTextarea").value =
document.getElementById("myContentEditable").innerHTML;
return true;
}
<form action='whatever' onsubmit='return copyContent()'>...
If anyone is interested I patched up a solution with VueJS for a similar problem. In my case I have:
<h2 #focusout="updateMainMessage" v-html="mainMessage" contenteditable="true"></h2>
<textarea class="d-none" name="gift[main_message]" :value="mainMessage"></textarea>
In "data" you can set a default value for mainMessage, and in methods I have:
methods: {
updateMainMessage: function(e) {
this.mainMessage = e.target.innerText;
}
}
"d-none" is a Boostrap 4 class for display none.
Simple as that, and then you can get the value of the contenteditable field inside "gift[main_message]" during a normal form submit for example, no AJAX required. I'm not interested in formatting, therefore "innerText" works better than "innerHTML" for me.
Does it NEED to be standard form submission? If you cannot or do not want use a form with inputs, you may try AJAX (XMLHttpRequest + FormData), through which you could perform asynchronous requests and control better how response shows up.
If you want it even simpler, try jQuery's $.ajax function (also $.get and $.post). It sends data using simple JS objects.
Made a fully working example based on Rob's idea:
After hitting submit, the (hidden) textarea is updated with the table-data, in JSON-format.
(return true to submit)
function copyContent() {
const table = [];
$("tr").each(function() {
const row = [];
$("th, td", this).each(function() {
row.push($(this).text());
});
table.push(row);
});
$("#rows").val(JSON.stringify(table));
// return true to submit
return false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form onsubmit='return copyContent()'>
<textarea name="rows" id="rows" rows="4"></textarea>
<button type="submit">Submit</button>
</form>
<table class="table table-striped">
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
</tr>
</thead>
<tbody>
<tr>
<td contenteditable="true">edit </td>
<td contenteditable="true">me</td>
</tr>
<tr>
<td contenteditable="true">please</td>
<td contenteditable="true">😊</td>
</tr>
</tbody>
</table>