How to use native html form with Angular 5 - javascript

I'm trying to add simple form element which must not be controlled by Angular.
The goal is to POST file download request, passing authentication token with use of hidden input.
Form code:
<form action="api/admin/codes-csv" method="POST" target="_blank">
<input type="hidden" name="token" value="{{token}}" />
<input class="admin-link" type="submit" value="Download Codes" />
</form>
At server side (aspnet core) I'm returning FileResult with CSV data to download.
This approach worked well with AngularJS but with Angular 5 it does not post to the server (request never happens actually).
If add another <input type="submit" /> right in browser DOM explorer, it works. I've tried to add another submit after page load by the script, but Angular seems to somehow override the behavior and it still doesn't work.
So what I need is seems to stop Angular doing anything with this form and make it act as plain html form.

At first: Are You include FormsModule ?
and try
<button type="submit" class="admin-link">Download Codes</button>

This is not a precise answer, because I was unable to make the form work.
But I was able to make file download with use of native HttpClient & FileSaver plugin.
1) Using my API authenticated via http headers, I'm providing my data as JSON with "text" property containing my CSV: { text: "hello,world,etc" }
2) after getting this result with usual API call, I'm using FileSaver (https://github.com/eligrey/FileSaver.js) to save with proper name, so something like this:
Template:
<a (click)="DownloadCsv()">Download All</a>
Component:
DownloadCsv() {
this.ApiService.Admin.CodesCsv.Post()
.subscribe(result => {
var blob = new Blob([result.text], { type: 'text/csv' });
fs.saveAs(blob, "codes.csv");
});
}
As a result, save dialog with proper file name appears. The ApiService is just a wrapper for native http client, which appends auth headers, handles errors and adds strong-typed definitions.

You use ngNoForm if you want the following:
To import the FormsModule but skip its usage in some forms, for example, to use native HTML5 validation, add the ngNoForm and the tags won't create an NgForm directive.
Source: https://angular.io/api/forms/NgForm#description
Similar answer: https://stackoverflow.com/a/49989002/1918775

Related

How to submit a form in Vue, redirect to a new route and pass the parameters?

I am using Nuxt and Vue and I am trying to submit a form, redirect the user to a new route including the submitted params, send an API request to get some data and then render that data.
I achieved this by simply setting the form action to the new path and manually adding all the URL parameters to the API request.
First I create a simple form with the route /search.
<form action="/search">
<input type="text" name="foobar">
<button type="submit">Submit</button>
</form>
When submitting the form the user leaves the current page and gets redirected to the new page. The URL would now look like this: http://www.example.com/search?foobar=test. Now I fetch the foobar parameter by using this.$route.query.foobar and send it to my API.
However the problem in my approach is when submitting the form the user leaves the current page and a new page load will occur. This is not what we want when building progressive web apps.
So my question is how can I submit a form in Nuxt/Vue and redirect to a new route including the submitted parameters?
The default behavior of <form> is to reload the page onsubmit. When implementing SPA's it would be better to avoid invoking default behavior of <form>.
Making use of router module which is available out-of-box in nuxtjs will enable all the redirection controls to flow within the application. if we try to trigger events available via <form> then browser reload will occur. This has to be avoided.
So my question is how can I submit a form in Nuxt/Vue and redirect to
a new route including the submitted parameters?
You can try below approach
First
Use .stop.prevent modifiers to prevent the submit button from invoking default <form> behavior. This is similar to using event.stopPropagation(); and event.preventDefault(); in jQuery
<form>
<input type="text" name="foobar" v-model="foobar">
<button type="submit" #click.stop.prevent="submit()">Submit</button>
</form>
Then
Create
vue model object foobar
vue method submit
Use this.$router.push to redirect to next page. This will enable the control flow to stay inside the SPA. if you want to send any data into server then you can do it before invoking this.$router.push else you can redirect and continue your logic.
export default {
data(){
return {
foobar : null
}
},
methods: {
submit(){
//if you want to send any data into server before redirection then you can do it here
this.$router.push("/search?"+this.foobar);
}
}
}
submitClick(){
this.$router.push({path: '/search', query:{key: value}})
}
<form #submit.stop.prevent="submitClick">
<input v-model="keyword">
<button type="submit">Search</button>
</form>
This is the right way to achieve a SPA with form submit. it supports enter key and in submitClick, there can be any logic before submitting
just add this:
#submit.prevent="false"
<form #submit.prevent="false">
<div class="form-group">
</div>
</form>
i hope this be useful for u :)

Inform AngularJS about file upload with Django

For my webpage I use Django 1.9 for the server-side and AngularJs for some client-side tasks (validation etc).
Also for the CSS I use Bootstrap (and the Angular-Ui).
Now I created the forms I need in Django which inserts them on the actual page. Amongst others, I have an input field of type file which lets the user upload a file.
When the user has chosen a file, I would like to do some checks in AngularJs. The problem is: I have no clue how I can get some kind of callback from Django to know that the upload-file window was closed.
My current solution involves a plain javascript function which is bound to the upload field and calls an AngularJs function, but this does not work properly.
So in my forms.py it looks like that:
class UploadForm(forms.Form):
fa_file = forms.FileField(label='Select a Fasta file',
widget=forms.TextInput(attrs={'type': 'file'})
The part of the html page where this field is inserted looks like that:
<div class="panel-body">
<input type="text" id="uploadFile" placeholder="Choose File" disabled="disabled"/>
<div class="file-upload btn btn-sm btn-primary">
<span>Upload</span>
{{ form.fa_file }}
</div>
</div>
The javascript function which is bound to the file-upload field is:
<script>
document.getElementById("id_fa_file").onchange = function () {
document.getElementById("uploadFile").value = this.value;
angular.element(this).scope().changeFaFileValue(this.value);
};
</script>
This on change method is executed whenever the user finishes choosing a file. Essentially this is the behavior I want to achieve and the AngularJS function of my controller 'changeFaFileValue' is executed as well.
But it seems that the execution happens in its own scope. I can tell because I have a watcher in my AngularJS controller for a variable which is changed in 'changeFaFileValue' and this watcher is not triggered when the function is called via this plain Javascript on change function.
But if I call the 'changeFaFileValue' from somewhere in my controller, the watcher executes as expected.
The methods in the controller look like this:
$scope.$watch('allow_submit', function(){
console.log("IT WORKED.");
});
$scope.changeFaFileValue = function(newPath){
$scope.fa_file_js = newPath;
$scope.allow_submit = !$scope.allow_submit;
}
I think I am missing something important here.
Can you please tell me what would be the correct way to achieve the desired behavior? Is my approach correct at all?

Return file for Saving from HttpPost Asp.Net MVC method

I have an Asp.Net MVC project, and on one page of it, user can edit loaded data into table(change images, strings,items order, etc...).
After all edits have made, the client pushes Download button, and save the resulted xml-file on his hard-drive for the next manipulations in future.
So i have a simple html form:
<form name="mainForm" data-ng-submit="sendForm()" ng-controller="ImportController" novalidate enctype="multipart/form-data">
<!-- table structure definition removed for briefing -->
<td>
{{data.Items[$index].Id}}
</td>
<td>
<img class="center-cropped" ng-src="data:image/jpg;base64, {{data.Items[$index].Image}}">
</td>
<td>
<input class="form-control" type="text" value="{{data.Items[$index].LastName}}" />
</td>
<td>
<input class="form-control" type="text" value="{{data.Items[$index].FirstName}}" />
</td>
<td>
<input class="form-control" type="text" value="{{data.ClaimItems[$index].MiddleName}}" />
</td>
<input class="btn-success" id="submit-btn" type="submit" data-ng-disabled="mainForm.$invalid" value="Download" />
</form>
This form data is sent through angularJs function call which looks like:
$scope.sendForm = function () {
// some preparations to send image data through json
for (var i = 0; i < $scope.data.Items.length; i++) {
$scope.data.Items[i].ImageAsString = $scope.data.Items[i].Image;
}
$http.post("Download", { array: $scope.data })
.success(function (responseData) {
console.log(responseData);
})
.error(function (responseData) {
console.log("Error !" + responseData);
});
};
After this function is called, the prepared http post request is sent to asp.net mvc Download action:
[HttpPost]
public FileResult Download(ItemsArrayWrapper array)
{
// here goes incoming data processing logic
// ...
return File(array.ConvertToItemsArray().Serialize(), "text/xml", name);
}
I want my Download method to return FileResult, so, that a file saving dialog will appear on the client. But nothing is happening.
I've tryed to construct various Response headers, to return different MimeTypes, change return types of Download method, and even tryed to call [HttpGet] method from Download method, but still nothing is appeared on the client.
Searched in browser network monitoring - there is only one POST request is sent.
Is it possible to send data from HttpPost method to client, that has been called from angularJs function in a such way? What i am missing, and why the saving dialog is not showed in browser?
Or can anyone suggest any other more suitable solutions to achieve this?
I want my Download method to return FileResult, so, that a file saving
dialog will appear on the client. But nothing is happening.
It's normal that nothing is happening. I would recommend you not using AJAX for downloading files. Just construct a normal hidden HTML form and then auto-submit this form to the Download controller action. Then the File Save dialog will appear to prompt the user for saving the file.
If you absolutely need to do this using AJAX then it should be noted that you could use the HTML5 FileAPI that allow you to save the binary response in an AJAX callback. But note that will work only in modern browsers and if you need to support some older browsers in your website you will need the first approach anyway.

Upload files without refreshing the page by using ajax post

I have a page file-upload.jsp with the code snippet below:
<form action="" id="frmupload" name="frmupload" method="post" enctype="multipart/form-data">
<input type="file" id="upload_file" name="upload_file" multiple="" />
<input type="submit" value="Update" />
</form>
I have 2 questions:
The moment I select some files, i.e the onchange event of the input type file, the file(s) should get uploaded.
I have a Java page that receives multipart request parameter and uploads the file to the said location. My problem is the form submission onchange, so that the Java file can proceed with further operations.
I googled and went through lot of articles. Some say it's not possible to upload files directly via Ajax, some say submit the form to an iframe via Ajax/jQuery.
I tried a lot of code from internet, such as this:
$(document).ready(function(){
$('upload_file').change(function(){
var data = new FormData();
data.append('file', $(this[0].files[0]));
$.ajax({
url: 'photo.jsp',
type: 'post',
contentType: attr('enctype', "multipart/form-data"),
data: data,
success: function(data){
alert(data);
}
})
});
});
but could not get the expected results.
I also need a progress bar for the upload operation.
Look at this example using an IFrame, is in PHP but changing the action should do the trick
Ajax Style File Uploading Using Hidden IFrame
Since you're already using jQuery, I would definitely go for the jQuery Form Plugin, which allows you to do form uploads via AJAX, even if the form contains a file input.
There is an example on its website available that shows how to display a progress bar.
Look at this example it is exact as you want
http://www.asp.net/ajaxlibrary/ajaxcontroltoolkitsamplesite/asyncfileupload/asyncfileupload.aspx

php form : twig parameter from javascript or textarea html

i have a textarea defined by an id
<textarea id='vegetable'> Tomato </textarea>
i have a button
<button type="button" onclick="MyFunction()">generate vegetable</button>
which trig a javascript in order to modify the content of the textarea
<script>
function MyFunction()
{
document.getElementById("vegetable").innerHTML = VegetableNameGenerator();
}
</script>
The problem is this php action :
<form action="{{ path('mypath', { 'myparam': ??? }) }}" method="post" >
<input type="submit" />
</form>
??? must be the content of the textarea (which is also known by the javascript code) but i don't know how to access it in twig.
I guess there are several way of doing that : jquery, dom, global variable twig... any syntax example would be great.
This is impossible in the way you're describing it.
When a request is made to the server, twig renders the page, then it is sent to the browser, and then javascript can run.
There are options for how to make this work:
Create a controller action which returns the rendered path when you call it using a GET request with the provided parameter. Then create an event listener on the submit button that blocks the submit process until it has retrieved the route via AJAX and modified the form's action attribute.
Redirect from your controller to the path you want displayed. myparam will be included in the post data, so you can redirect from your controller action after you've handled the form.
$this->redirect($this->get('router')
->generate('mypath',
array('myparam'=>
$this->getRequest()->get('myparam')
),
true);

Categories

Resources