Cant post the data using Modal with Ajax in Razor Pages - html

This is the index file code:
public IList<Employee> Employee { get; set; }
public async Task OnGetAsync()
{
Employee = await _context.Employee.ToListAsync();
}
public JsonResult EmployeeList()
{
var data = _context.Employee.ToList();
return new JsonResult(data);
}
[HttpPost]
public JsonResult AddEmployee(Employee e)
{
var emp = new Employee()
{
Name = e.Name,
Age = e.Age,
Email = e.Email
};
_context.Employee.Add(emp);
_context.SaveChanges();
return new JsonResult("Success!!!");
}
Button to open Modal:
<button class="btn btn-info mb-3" id="btn1">Add Employee</button>
The Modal:
<!-- The Modal -->
<div class="modal Add-Emp">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title">Add Employee</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<!-- Modal body -->
<div class="modal-body">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label>Name</label>
<input type="text" placeholder="Enter Name" class="form-control" id="Name" autocomplete="off"/>
</div>
<div class="form-group">
<label>Age</label>
<input type="text" placeholder="Enter Age" class="form-control" id="Age" autocomplete="off"/>
</div>
<div class="form-group">
<label>Email</label>
<input type="text" placeholder="Enter Email" class="form-control" id="Email" autocomplete="off"/>
</div>
</form>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button class="btn btn-primary" onclick="AddEmployee();">Save</button> I
<button class="btn btn-danger btn-default" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
The Js Code:
$("#btn1").click(function () {
$(".Add-Emp").modal("show")
})
function AddEmployee() { debugger
var objData = { Name: $("#Name").val(), Age: $("#Age").val(), Email: $("#Email").val() }
$.ajax({
url: "Pages/Employees/Index/AddEmployee",
type: "Post",
data: objData,
contentType: "application/xxx-www-form-url-encoded; charset=utf-8",
dataType: "json",
success: function () { alert("Data Saved"); },
error: function () { alert("Error!!!"); }
})
}
Modal opens on click But data does not get posted on clicking the save button it displays alert "Error!!!" defined in failure of ajax requestㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ

1.You maybe not familiar with Razor Pages, Razor pages uses OnGet and OnPost to deal with the Http Get and Post request. If you need another Get or Post method in current PageModel, you need define the method name like: OnGetHandlerName or OnPostHandlerName.
2.If your .cshtml.cs file located like: Pages/Employees/Index.cshtml.cs, the request url should be:/Employees/Index. If you set the handler in your PageModel, the request url should be:/Employees/Index?handler=xxx.
3.For how to use Ajax in Razor Pages, Razor Pages enable anti-forgery token validation by default, so you need add this token to header in ajax.
If you use form in Razor Pages, it will default generate an input with token. If not, you need add #Html.AntiForgeryToken() manually.
A whole working demo you could follow:
Page(Pages/Employees/Index.cshtml):
#page
#model IndexModel
<button class="btn btn-info mb-3" id="btn1">Add Employee</button>
<div class="modal Add-Emp">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title">Add Employee</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<!-- Modal body -->
<div class="modal-body">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label>Name</label>
<input type="text" placeholder="Enter Name" class="form-control" id="Name" autocomplete="off" />
</div>
<div class="form-group">
<label>Age</label>
<input type="text" placeholder="Enter Age" class="form-control" id="Age" autocomplete="off" />
</div>
<div class="form-group">
<label>Email</label>
<input type="text" placeholder="Enter Email" class="form-control" id="Email" autocomplete="off" />
</div>
</form>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button class="btn btn-primary" onclick="AddEmployee();">Save</button> I
<button class="btn btn-danger btn-default" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
#section Scripts
{
<script>
$("#btn1").click(function () {
$(".Add-Emp").modal("show")
})
function AddEmployee() {
debugger
var objData = { Name: $("#Name").val(), Age: $("#Age").val(), Email: $("#Email").val() }
$.ajax({
url: "/Employees/Index?handler=AddEmployee",
type: "Post",
data: JSON.stringify(objData), //change here...
contentType: "application/json; charset=utf-8", //change here...
headers: {
RequestVerificationToken:
$('input:hidden[name="__RequestVerificationToken"]').val()
}, //add this....
dataType: "json",
success: function () { alert("Data Saved"); },
error: function () { alert("Error!!!"); }
})
}
</script>
}
Pages/Employees/Index.cshtml.cs:
public class IndexModel : PageModel
{
//...
public IList<Employee> Employee { get; set; }
public async Task OnGetAsync()
{
Employee = await _context.Employee.ToListAsync();
}
public JsonResult OnGetEmployeeList()
{
var data = _context.Employee.ToList();
return new JsonResult(data);
}
public JsonResult OnPostAddEmployee([FromBody]Employee e)
{
var emp = new Employee()
{
Name = e.Name,
Age = e.Age,
Email = e.Email
};
return new JsonResult("Success!!!");
}
}

Related

Angular2 Bootstrap modal user inputs + image

I am using a bootstrap model to create and update groups. on the backend side, there are no issues. Below I have my ts and HTML code I used. the modal works fine, but I don't know how to return any values from my form to my ts file so i can use it in an API call.
also for an image I need formdata
in short:
What's the issue: Returning user inputs(+image) in angular 2
!edit! the error i get is:
_co.save is not a function
html:
<app-modal #modal>
<div class="app-modal-header">
header
</div>
<div class="app-modal-body">
<form #modalform="ngForm" (ngSubmit)="save(modalform.value)" >
First name: <input type="text" name="FirstName" ngModel><br>
Last name: <input type="text" name="LastName" ngModel><br>
image: <input type="file" name="image" ngModel><br>
</form>
</div>
<div class="app-modal-footer">
<button type="button" class="btn btn-default" (click)="modal.hide()">Close</button>
<button type="button" class="btn btn-primary" (click)="modal.hide()">Save changes</button>
</div>
</app-modal>
TS:
#Component({
selector: 'app-modal',
template: `
<div (click)="onContainerClicked($event)" class="modal fade" tabindex="-1" [ngClass]="{'in': visibleAnimate}"
[ngStyle]="{'display': visible ? 'block' : 'none', 'opacity': visibleAnimate ? 1 : 0}" style=" background: rgba(0,0,0,0.6);">
<div class="modal-dialog" style="padding-top: 25%;">
<div class="modal-content">
<div class="modal-header">
<ng-content select=".app-modal-header"></ng-content>
</div>
<div class="modal-body">
<ng-content select=".app-modal-body"></ng-content>
</div>
<div class="modal-footer">
<ng-content select=".app-modal-footer"></ng-content>
</div>
</div>
</div>
</div>
`
})
export class ModalComponent {
public visible = false;
public visibleAnimate = false;
public show(): void {
this.visible = true;
setTimeout(() => this.visibleAnimate = true, 100);
}
public save(): void{
}
public hide(): void {
this.visibleAnimate = false;
setTimeout(() => this.visible = false, 300);
}
public onContainerClicked(event: MouseEvent): void {
if ((<HTMLElement>event.target).classList.contains('modal')) {
this.hide();
}
}
}
fixed it by placing the save function in the other component

value data not added to request on submit and label interference on the value

i have got two issues..looking forward for solution
issue 1: I have a ui-calendar ,on clicking the any date a new form will be opened which will have two input forms as shown.
app.controller("MyAddController", function($scope, $http) {
$scope.test = {};
$scope.add = function() {
console.log("------------>"+JSON.stringify($scope.test));
$http({
url: "rest/leave/create",
method: "POST",
data: JSON.stringify($scope.test),
headers: {'Content-Type': 'application/json'}
}).success(function(data, status, headers, config) {
if (data) {
$scope.data = data;
alert("success");
}
}).error(function(data, status, headers, config) {
alert("error");
})
}
});
<!-- Modal Structure -->
<div id="modal1" class="modal" ng-controller="MyAddController">
<div class="modal-content">
<div class="row modal-form-row">
<div class="input-field col s5">
<input id="startDate" type="text" class="validate" value="{{selectionDate.startdate1}}" readonly="true" ng-bind="test.startDate" >
<label for="startDate">Start Date</label>
</div>
<div class="input-field col s5">
<input id="endDate" type="text" class="validate" value="{{selectionDate.enddate1}}" readonly="true" ng-bind="test.endDate">
<label for="endDate">End Date</label>
</div>
</div>
</form>
</div>
</div>
<div class="modal-footer">
<button class="btn waves-effect waves-light" type="submit" ng-click="add()" name="action">Submit
<i class="material-icons right">send</i>
</button>
</div>
</div>
The problem with the above code is that the value of the input fields are not included while passing the data to the server as it was not typed.i want the field to be disabled ie not editable but the value from {{Selectdate.startdate}} and {{selectDate.endDate}} should be included in the request.So please let me know how to do this.(selectionDate is in $rootscope and test in $scope).
2.Second issue.
From the same code above ,with a label the value {{selectedDate.startDate1}} overlaps with the label text as shown below
How to make the label move up like other input fields.
Any kind of help would be appreciated

OnChange Typescript input

I want to be able to trigger an on change when a file is selected from a input(file). I want the triggered event to set a textbox to be the name of the file.
I am using HTML5, Typescript and Angular2. I can't figure out or find an example of exactly how to produce the behavior I am after.
see my code below:
component.ts
import { Component } from '#angular/core';
import { Http } from '#angular/http';
import { Headers, RequestOptions } from '#angular/http';
#Component({
selector: 'testConnection',
// ignore error on require
template: require('./testConnection.component.html')
})
export class TestConnectionComponent {
public http: Http;
public requestData: RequestData;
public constructor(http: Http) {
this.http = http;
(<HTMLInputElement>document.getElementById('fileInput')).onchange = (ev: Event) => {
var fileInput = (<HTMLInputElement>ev.srcElement).files[0];
var fileTextbox = (<HTMLInputElement>document.getElementById('fileTextbox'));
fileTextbox.value = fileInput.name;
}
}
public testButtonClick() {
// Iniatialise Request object
let request: RequestData;
request = { "CountryCode": "", "SiteIDList": "" };
// Get site(s)
var siteIdList = (<HTMLInputElement>document.getElementById('siteIDInput')).value;
// Get selected country
var countryCode = (<HTMLInputElement>document.getElementById('countryDropdown')).value;
// Veryify contents is just site ids.
// TODO
request.CountryCode = countryCode;
request.SiteIDList = siteIdList;
// Set Http POST options
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
// Call Api with test connection data
this.http
.post('/api/TestConnection/TestConnection', JSON.stringify(request), options)
.subscribe(data => {
// alert request ok
alert('ok');
}, error => {
// Log error
console.log(error.json());
});
}
}
interface RequestData {
SiteIDList: string;
CountryCode: string;
}
component.html
<h2>Test Site Connection</h2>
<p>This will allow you to check the connectivity of a set of sites by either individually or uploading a CSV file of Site IDs.</p>
<br />
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Manual Test</h3>
</div>
<div class="panel-body">
<p>
Select the country and the sites you want to test.
</p>
<ul>
<li>Multiple sites can be selected using commas (,).</li>
<li>you can see results in the Site Connection Results tab</li>
</ul>
<br />
<!--Replace with lookup to enabled countries-->
<div class="form-group col-lg-4">
<div class="col-lg-6">
<select class="form-control" id="countryDropdown">
<option>Select Country</option>
<option>US</option>
<option>SG</option>
<option>NL</option>
</select>
</div>
</div>
<div>
<div class="col-lg-4">
<input type="text" class="form-control" placeholder="SiteID(s)" id="siteIDInput" />
</div>
<button class="btn btn-primary" (click)="testButtonClick()">Test</button>
</div>
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Upload file</h3>
</div>
<div class="panel-body">
<div>
<p>Upload a CSV file of sites to test all at once.</p>
<br />
<div class="col-lg-4">
<input type="text" class="col-lg-4 form-control" id="fileTextbox" disabled/>
</div>
<label class="btn btn-primary">
Browse <input type="file" id="fileInput" style="display:none;" onchange="{ setFileName() }"/>
</label>
<button class="btn btn-primary" (click)="searchButtonClick()">Test</button>
</div>
</div>
</div>
<div class="modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
Try using (change) event binding
<input type="file" id="fileInput" style="display:none;" (change)="setFileName()"/>
If you need to retrieve the file name before uploading it you can do it this way :
#Component({
selector: 'my-app',
template: `
<div>
<input type="file" (change)="onChange($event)"/>
</div>
<p>Filename : {{filename}}</p>
`,
providers: []
})
export class AppComponent {
filename: string;
constructor() { }
onChange(event) {
this.filename = event.srcElement.files[0].name;
}
}
Here is a working plunker

Remove Previously selected image in dropzone

I am using dropzone with a form on a modal. I have one button that is 'Add Slider'. When I click on that button the modal is opened. In that modal I have attached an image on dropzone and click on cancel button. When I click on 'Add Slider' button again it shows the previously selected image in dropzone. I want to remove the previously selected image.
Html Code
<modal title="Manage HomeSlider" modaltype="modal-primary" visible="IsFormVisible">
<form name="frmHomeSlider" method="post" class="form-horizontal bv-form" novalidate="novalidate" ng-submit="frmHomeSlider.$valid && fnSaveHomeSlider()">
<modal-body>
<input type="hidden" class="form-control" name="ID" ng-model="HomeSlider.ID" />
<div class="form-group">
<label class="col-lg-3 control-label">Upload Slider Photo</label>
<div class="col-lg-9">
<div class="dropzone profileImage" customdropzone="dropzoneConfig">
<div class="dz-default dz-message">
<div ng-show="HomeSlider.FullPathPhoto==''">
<span>Upload photo here</span>
</div>
<img src="{{HomeSlider.FullPathPhoto}}" required />
</div>
</div>
<input type="hidden" name="Photo" ng-model="HomeSlider.HomeSliderPhoto" required />
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Image Name</label>
<div class="col-lg-9">
<input type="text" class="form-control input-sm" name="ImageName" ng-model="HomeSlider.ImageName" placeholder="Enter Image Name" required />
</div>
</div>
</modal-body>
<modal-footer>
<button type="submit" class="btn btn-blue" ng-disabled="frmHomeSlider.$invalid">Submit</button>
<button type="reset" class="btn btn-default" ng-click="fnShowHomeSliderForm(false)">Cancel</button>
</modal-footer>
</form>
</modal>
Js Code
$scope.dropzoneConfig = {
'options': { // passed into the Dropzone constructor
'url': ContentService.UploadHomeSliderPhoto,
'addRemoveLinks': true,
'acceptedFiles': 'image/*',
'uploadMultiple': false,
'maxFiles': 1,
'dictDefaultMessage': 'Upload your photo here',
'init': function () {
this.on('success', function (file, response) {
$scope.HomeSlider.HomeSliderPhoto = response.FileNames[0];
});
this.on('thumbnail', function (file) {
if (file.width < 1800 || file.height < 1200 || file.width > 1800 || file.height > 1200) {
file.rejectDimensions();
}
else {
file.acceptDimensions();
}
});
},
'accept': function (file, done) {
file.acceptDimensions = done;
file.rejectDimensions = function () {
done("The image must be at least 1800 x 1200px");
};
}
},
'eventHandlers': {
'sending': function (file, xhr, formData) {
},
'success': function (file, response) {
$scope.HomeSlider.HomeSliderPhoto = response.FileNames[0];
},
'error': function () {
$rootScope.Common.notifyDanger("Error accure while upload photo.")
}
}
};

Populate input using #Input inside Bootstrap 4 modal

I have a main page with a table that when a row is clicked on, it uses #Output to send out that row's data (I've already confirmed the data is being sent properly by using it in another place in the project). I then have a Bootstrap 4 modal that pops up when I click the button on the left below where it says "Data Point Information". What I need to do is take the data from the row that was clicked on, and populate the form inside the modal with it.
Main Page:
Modal:
HTML for the modal:
<div class="modal fade" id="myModal2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog bodyWidth">
<div class="modal-content wide">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Update Data Point</h4>
</div>
<div class="modal-body">
<form class="form-inline" [formGroup]="updateForm" (ngSubmit)="submitForm(updateForm.value)">
<div class="row">
<div class="form-group" [ngClass]="{'has-error':!updateForm.controls['dataPoint'].valid && updateForm.controls['dataPoint'].touched}">
<label>Data Point:</label>
<input class="form-control special" type="text" [formControl]="updateForm.controls['dataPoint']">
</div>
<div class="form-group move" [ngClass]="{'has-error':!updateForm.controls['ICCP'].valid && updateForm.controls['ICCP'].touched}">
<label >ICCP:</label>
<input type="text" class="form-control special" [formControl]="updateForm.controls['ICCP']">
</div>
<div class="form-group" [ngClass]="{'has-error':!updateForm.controls['startDate'].valid && updateForm.controls['startDate'].touched}">
<label>Start Date:</label>
<input [value]="getDate('start')" class="form-control special" type="text" [formControl]="updateForm.controls['startDate']" style="margin-right: 4px;">
</div>
<div style="display:inline-block">
<ngb-datepicker id="special" *ngIf="startCheck;" [(ngModel)]="startDate" (ngModelChange)="showDatePick(0)" [ngModelOptions]="{standalone: true}"></ngb-datepicker>
</div>
<button type="button" class="btn icon-calendar closest" (click)="showDatePick(0)"></button>
<div class="form-group" [ngClass]="{'has-error':!updateForm.controls['endDate'].valid && updateForm.controls['endDate'].touched}">
<label >End Date:</label>
<input [value]="getDate('end')" class="form-control special" type="text" [formControl]="updateForm.controls['endDate']">
</div>
<div style="display:inline-block">
<ngb-datepicker id="special" *ngIf="endCheck;" [(ngModel)]="endDate" (ngModelChange)="showDatePick(1)" [ngModelOptions]="{standalone: true}"></ngb-datepicker>
</div>
<button type="button" class="btn icon-calendar closer" (click)="showDatePick(1)"></button>
</div>
</form>
</div>
<div class="modal-footer">
*All Fields Are Required. End Date must be after Start Date
<button type="submit" class="btn" [disabled]="!updateForm.valid" data-dismiss="modal">Update</button>
<button type="button" (click)="resetForm()" class="btn" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
Typescript for the modal:
#Component({
selector: 'update-validation',
styleUrls: ['../app.component.css'],
templateUrl: 'update.component.html',
providers: [DatePipe]
})
export class UpdateComponent {
#Input() receivedRow:DataTable;
public dt: NgbDateStruct;
public dt2: NgbDateStruct;
public startCheck: boolean = false;
public endCheck: boolean = false;
updateForm : FormGroup;
constructor(fb: FormBuilder, private datePipe: DatePipe){
this.updateForm = fb.group({
'dataPoint' : [DPS[0].tDataPoint, Validators.required],
'ICCP' : [DPS[0].tICCP, Validators.required],
'startDate' : [DPS[0].tStartDate, Validators.required],
'endDate' : [DPS[0].tEndDate, Validators.required]
}, {validator: this.endDateAfterOrEqualValidator})
}
resetForm(){
location.reload();
//this.updateForm.reset();
}
submitForm(value: any){
console.log(value);
}
public getDate(dateName: string) {
let workingDateName = dateName + 'Date';
let timestamp = this[workingDateName] != null ? new Date(this[workingDateName].year, this[workingDateName].month-1, this[workingDateName].day).getTime() : new Date().getTime();
this.updateForm.controls[dateName + 'Date'].setValue(this.datePipe.transform(timestamp, 'MM/dd/yyyy'));
}
public showDatePick(selector):void {
if(selector === 0) {
this.startCheck = !this.startCheck
} else {
this.endCheck = !this.endCheck;
}
}
endDateAfterOrEqualValidator(formGroup): any {
var startDateTimestamp, endDateTimestamp;
for(var controlName in formGroup.controls) {
if (controlName.indexOf("startDate") !== -1) {
startDateTimestamp = Date.parse(formGroup.controls[controlName].value);
}
if (controlName.indexOf("endDate") !== -1) {
endDateTimestamp = Date.parse(formGroup.controls[controlName].value);
}
}
return (endDateTimestamp < startDateTimestamp) ? { endDateLessThanStartDate: true } : null;
}
}
HTML from the main page that places modal there using it's selector (toSend is of type DataTable which is the data from the row I am sending from the main page's Typescript):
<update-validation [receivedRow]='toSend'></update-validation>
Since I'm using #Output and #Input, I'm not sure why receivedRow in my Typescript is undefined.
The reason is that when your component of modal initialized, there were not any receivedRow. You should control it with *ngIf directive and ngOnChange method like that;
//xyz is just any field on your parent component
//in html
<div *ngIf="xyz">
<update-validation [receivedRow]="xyz"></update-validation>
</div>
//in component of modal
ngOnChanges(){
if(receivedRow){
//do whatever you want
}
}