Firstly apologies that post looks a bit long winded (it is just repeated code, so looks longer than it is). I'm trying to implement a multiple level cascading dropdown - It works fine for the initial and first level (COLUMN1 & COLUMN2) but not for COLUMN3.
Here is the controller:
public JsonResult GetCol1()
{
using (EntityName db = new EntityName())
{
var ret = db.TABLE_NAME.Select(x => new { x.COLUMN1 }).Distinct().ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}
[HttpPost]
public JsonResult GetCol2(string col1)
{
using (EntityName db = new EntityName())
{
var ret = db.TABLE_NAME.Where(x => x.COLUMN1 == col1).Select(x => new { x.COLUMN2 }).Distinct().ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}
[HttpPost]
public JsonResult GetCol3(string col1, string col2)
{
using (EntityName db = new EntityName())
{
var ret = db.TABLE_NAME.Where(x => x.COLUMN1 == col1).Where(x => x.COLUMN2 == col2).Select(x => new { x.COLUMN3 }).Distinct().ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}
Here is the JS:
app.controller('DropdownPopulation', function ($scope, $http) {
//$http service for Getting Column1
$http({
method: 'GET',
url: '/Data/GetCol1'
})
.success(function (data) {
$scope.Col1Data = data;
});
//$http service for getting Column2
$scope.GetCol2 = function () {
$http({
method: 'POST',
url: '/Data/GetCol2',
data: JSON.stringify({ COLUMN1: $scope.col1 })
}).
success(function (data) {
$scope.Col2Data = data;
});
};
//$http service for getting Column3
$scope.GetCol3 = function () {
$http({
method: 'POST',
url: '/Data/GetCol3',
data: JSON.stringify({ COLUMN1: $scope.col1, COLUMN2: $scope.col2 })
}).
success(function (data) {
$scope.Col3Data = data;
});
};
};
Finally here is the html / angular:
<!-- Column 1 -->
<div ng-controller="DropdownPopulation">
<div class="form-group">
<label class="control-label col-sm-2" for="Column1">Column1</label>
<div class="col-sm-10">
<select class="form-control" name="Column1"
data-ng-model="col1" id="Column1"
data-ng-options="c.COLUMN1 as c.COLUMN1 for c in Col1Data "
data-ng-change="GetCol2()">
<option value="" disabled selected>Select Col 1</option>
</select>
</div>
</div>
<!-- Column 2 -->
<div class="form-group">
<label class="control-label col-sm-2" for="Column2">Column2</label>
<div class="col-sm-10">
<select class="form-control" name="Column2"
data-ng-model="col2" id="Column2"
data-ng-options="c.COLUMN2 as c.COLUMN2 for c in Col2Data "
data-ng-change="GetCol3()"
data-ng-disabled="!Col1Data" >
<option value="" disabled selected>Select Col 2</option>
</select>
</div>
</div>
<!-- Column 3 -->
<div class="form-group">
<label class="control-label col-sm-2" for="Column3">Column3</label>
<div class="col-sm-10">
<select class="form-control" name="Column3"
data-ng-model="col3" id="Column3"
data-ng-options="c.COLUMN3 as c.COLUMN3 for c in Col3Data"
data-ng-disabled="!Col2Data" >
<option value="" disabled selected>Select Col 3</option>
</select>
</div>
</div>
</div>
Col3Data is actually returning empty when there is data in the database.
If you know why Col3Data is not returning back anything then your help would be most appreciated.
Many thanks
Shaheen
Okay i found out what the problem was. When doing the following:
data-ng-options="c.COLUMN1 as c.COLUMN1 for c in Col1Data
I was using 'values' for the first part rather than a 'key', so this was not returning data back.
changing to the following worked:
data-ng-options="c.COLUMN1_KEY as c.COLUMN1 for c in Col1Data
Viplock, thanks for your help as I found:
var dataToSend={ COLUMN1: $scope.col1, COLUMN2: $scope.col2 };
very helpful.
Regards,
Shaheen K
If there will be some issue with digest cycle not worked , you can try using $scope.$apply() like
Update For sending data
$scope.GetCol3 = function () {
var dataToSend={ COLUMN1: $scope.col1, COLUMN2: $scope.col2 };
$http({
method: 'POST',
url: '/Data/GetCol3',
data: dataToSend
}).
success(function (data) {
$scope.Col3Data = data;
$scope.$apply();
});
};
Related
I have a two onchange function for a page called create delivery request. One is when the dropdownlist of receiver changes, then it should show the phone number & address of receiver selected. Another one is when the dropdownlist of delivery item changes, then it should set the max attribute for the quantity.
The url of both these are linked to the customized OnGet method in razor page.
However, usually the above Onget method is hit but the below one is not. And the above OnGet method can't get the dryfood with the passed ID as well, it is null inside. And the two jQuery ajax function doesn't work at all. I'm totally a beginner. Hope that there is someone who can help me. Thanks in advance.
In create.cshtml:
<div class="mb-3">
Receiver Name
<select id="receiver" asp-for="Delivery.ReceiverID" asp-items="Model.ReceiverList" class="form-control">
<option>--Select the Receiever--</option>
</select>
</div>
<div class="mb-3">
Receiver Phone
<span id="receiverphone" class="form-control">----</span>
</div>
<div class="mb-3">
Receiver Address
<div id="receiveradrs1" class="form-control">----</div>
<div id="receiveradrs2" class="form-control">----</div>
</div>
<div class="mb-3">
Delivery Item
<select id="deliveryitem" asp-for="DeliveryItem.DryFoodID" asp-items="Model.DeliveryItemList" class="form-control">
<option>--Select Delivery Item--</option>
</select>
</div>
<div class="mb-3">
Quantity
<input id="quantity" asp-for="DeliveryItem.Quantity" min="1" class="form-control" />
</div>
In create.csthml.cs, two customized OnGet method here:
public async Task<IActionResult> OnGetSetMaxQuantity(int id)
{
List<DryFoodDonation> dfdlist = await _db.DryFoodDonation.ToListAsync();
var dryfood = dfdlist.Where(d => d.Id == id).FirstOrDefault();
Debug.WriteLine(dryfood.DryFoodName + " " + dryfood.DryFoodRemainQuantity);
return new JsonResult(dryfood.DryFoodRemainQuantity);
}
public async Task<IActionResult> OnGetGetPhoneAdrs(int id)
{
List<User> receiverlist = await _db.User.Where(u => u.UserType.TypeID == 3).ToListAsync();
var selectreceiver = receiverlist.Where(d => d.UserID == id).FirstOrDefault();
Debug.WriteLine(selectreceiver.UserName + " " + selectreceiver.UserPhone);
return new JsonResult(selectreceiver);
}
The jQuery AJAX function in a JavaScript file:
$(document).ready(function () {
$("#receiver").change(function () {
alert('Yes receiver here changed.');
var item = $(this).val();
$.ajax({
type: 'GET',
url: 'Create/?handler=GetPhoneAdrs',
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: {
'id': item
},
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (data) {
$('#receiverphone').html(data.UserPhone);
$('#receiveradrs1').html(data.UserAdrs1);
$('#receiveradrs2').html(data.UserAdrs2);
}
});
});
$("#deliveryitem").change(function () {
alert('Yes item here changed.');
var item = $(this).val();
$.ajax({
type: 'GET',
url: 'Create/?handler=SetMaxQuantity',
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: {
"id": item
},
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (data) {
$("#quantity").attr({
"min": 1,
"max": data
});
}
});
});
});
Please help me with this. I can't solve this problem for a few weeks. Thank you!
// cshtml.cs
const sendMe = async function (someData) {
$.ajax({
type: 'POST',
dataType: 'json',
url: '/ControllerName/MethodNameInController',
data: { someData: someData },
success: function (response) {
if (response != null && response.statusCode == 200) {
..
} else {
..
}
}
});
}
//Controller
[HttpPost("MethodNameInController")]
public IActionResult MethodNameInController([FromForm] string someData) {
..
}
I would like to post a request via AJAX to a Controller with a model prefix. I need a prefix as I have two forms on one page with similiar model properties ("asp-for" is generating similiar IDs and Names). I'm using .NET Core 3.1.
Request post works fine without a prefix. When I'm using a prefix like in the example below, passed model is null in Controller:
Controller with prefix
[HttpPost]
public async Task<IActionResult> Save([Bind(Prefix="ShipmentAddress"), FromBody]ShipToAddressViewModel model)
{
// model is null
...
return PartialView(ShipmentAdressFormView, model);
}
View with prefix
In my View I set the HTMLFieldPrefix as well:
#model ShipToAddressViewModel
#{
ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "ShipmentAddress";
}
...
$("body").on('submit','#formShipmentAddress', function (e) {
// Getting the data (see passed JSON below)
var formData = new FormData(<HTMLFormElement>document.getElementById('formShipmentAddress'));
var object = {};
formData.forEach(function (value, key) {
object[key] = value;
});
var data = object;
$.ajax({
type: "POST",
url: url,
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: (data) => {
success(data);
}
});
});
Passed JSON payload with prefix
{"ShipmentAddress.ID":"3","ShipmentAddress.Name":"Eddard Stark","ShipmentAddress.Name2":"c/o Ned",..."}
Model
public class ShipToAddressViewModel
{
public int ID { get; set; }
[Display(Name="Name")]
public string Name { get; set; }
[Display(Name = "Name 2")]
public string Name2 { get; set; }
...
}
UPDATE
If I remove the prefix from keys of my objects, then it works, though more like a work around (Model binding starts by looking through the sources for the key ShipmentAddress.ID. If that isn't found, it looks for ID without a prefix.):
// Getting the data (see passed JSON below)
var formData = new FormData(<HTMLFormElement>document.getElementById('formShipmentAddress'));
var object = {};
formData.forEach(function (value, key) {
object[key.replace("ShipmentAddress.","")] = value;
});
var data = object;
For Asp.Net Core, there are two ways to bind the model, ModelBinding and JsonInputFormatter. For sending request with json, it will use JsonInputFormatter. Bind will not work with JsonInputFormatter.
Here is a working demo like below:
1.View:
#{
ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "ShipmentAddress";
}
#model ShipToAddressViewModel
<form id="formShipmentAddress">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ID" class="control-label"></label>
<input class="form-control" asp-for="ID">
<span asp-validation-for="ID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input class="form-control" asp-for="Name">
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name2" class="control-label"></label>
<input class="form-control" asp-for="Name2">
<span asp-validation-for="Name2" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
#section Scripts
{
<script>
$("body").on('submit', '#formShipmentAddress', function (e) {
e.preventDefault();
var id = parseInt($("#ShipmentAddress_ID").val());
var name = $("#ShipmentAddress_Name").val();
var name2 = $("#ShipmentAddress_Name2").val();
var data = {
ID: id,
Name: name,
Name2: name2
};
$.ajax({
type: "POST",
url: "/Home/Save",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: (data) => {
success(data);
}
});
});
</script>
}
2.Controller:
public async Task<IActionResult> Save([FromBody]ShipToAddressViewModel model)
{
//do your stuff...
}
3.Result:
I want to call a service through http for a dropdown list in angularjs. But, the function is not going to execute the http service method.
im binding the dropdown list by ajax call , after binding the ajax call i would like to show the details of the selected value from ajax call.
<script type="text/javascript">
var app = angular.module('myApp', [])
app.controller('myCtrl', function ($scope, $http, $window) {
$scope.DefaultLabel = "Loading.....";
var post = $http({
method: "POST",
url: "/PIRDetails/AjaxMethod",
dataType: 'json',
data: {},
headers: { "Content-Type": "application/json" }
});
post.success(function (data, status) {
$scope.DefaultLabel = "Please Select PIR Device";
$scope.Customers = data;
});
post.error(function (data, status) {
$window.alert(data.Message);
});
$scope.getPIRData = function (id) {
$http.get("/PIRDetails/GetPIRStatus/e203")
.then(function (response) {
$scope.myWelcome = response.data;
});
};
});
</script>
<div ng-app="myApp" ng-controller="myCtrl">
<select class="form-control" onchange="getPIRData(this.value);">
<option value="0" label="{{DefaultLabel}}"></option>
<option ng-repeat="customer in Customers" value="{{customer.Value}}">{{customer.Text}}</option>
</select>
</div>
Try ng-change and not onchange
<div ng-app="myApp" ng-controller="myCtrl">
<select class="form-control" ng-change="getPIRData(this.value);">
<option value="0" label="{{DefaultLabel}}"></option>
<option ng-repeat="customer in Customers" value="{{customer.Value}}">{{customer.Text}}</option>
</select>
</div>
A demo code here
As # sinkatonte mentioned in the comment, The way you use angularjs is completely incorrect. You don't need to define angularjs application and controller inside a function. Use the following way to correct your code.
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope, $http) {
$scope.getPIRData = function(id) {
$http.get("/PIRDetails/GetPIRStatus/e203")
.then(function (response) {
$scope.myWelcome = response.data;
});
};
});
<div ng-app="myApp" ng-controller="myCtrl">
<select class="form-control" ng-change="getPIRData(this.value);">
<option value="0" label="{{DefaultLabel}}"></option>
<option ng-repeat="customer in Customers" value="{{customer.Value}}">{{customer.Text}}</option>
</select>
</div>
Make sure the response.data in the $http returns data is in correct format and there is a value for this.value used in ng-change="getPIRData(this.value)
How do I send some data from the view back to the controller?
This is the select from where I get the data (sel1):
<div class="form-group" style="margin: 0 auto;">
<label for="sel1">Select a cat breed:</label>
<select class="form-control" id="sel1">
#foreach (var item in Model)
{
<option>
#Html.DisplayFor(modelItem => item.BreedName)
</option>
}
</select>
</div>
This is the script I tried to use to send data back:
<script>
$(document).ready(function () {
loadJasonData();
$("#sel1").change(function () {
loadJasonData();
});
});
function loadJasonData() {
$.ajax({
type: "POST",
url: "CatDetails",
//url: "/CatCompare/CatDetails", i also tried this of url
cache: false,
dataType: "json",
data: { name: $("#sel1").val() }
})
}
And finally the controller:
[HttpPost]
[HttpGet]
public ActionResult CatDetails(string name)
{
var breedName = db.Breeds.FirstOrDefault(b => b.BreedName == name);
ViewBag.name = breedName.BreedName;
ViewBag.lifeSpan = breedName.Lifespan;
ViewBag.height = breedName.Height;
ViewBag.weight = breedName.Weight;
ViewBag.shortDescription = breedName.ShortDescription;
return View();
}
First of all you have to add option value to your select:
<div class="form-group" style="margin: 0 auto;">
<label for="sel1">Select a cat breed:</label>
<select class="form-control" id="sel1">
#foreach (var item in Model)
{
<option value='#item.BreedName'>
#Html.DisplayFor(modelItem => item.BreedName)
</option>
}
</select>
</div>
Then change your loadJasonData() method to this
function loadJasonData() {
$.ajax({
type: "POST",
url: "/CatCompare/CatDetails",
cache: false,
dataType: "json",
data: { name: $("#sel1 option:selected").val() }
})
}
at the last remove [HttpGet] in your action
[HttpPost]
public ActionResult CatDetails(string name)
{
var breedName = db.Breeds.FirstOrDefault(b => b.BreedName == name);
ViewBag.name = breedName.BreedName;
ViewBag.lifeSpan = breedName.Lifespan;
ViewBag.height = breedName.Height;
ViewBag.weight = breedName.Weight;
ViewBag.shortDescription = breedName.ShortDescription;
return View();
}
Note: Your action returns a view. If you want to return json result you have to use return Json(yourData);
I am getting my data using json array via php now on edit operation when I got the data in select box on changing different values data is not updating .Any help would be appreciated.
$scope.rec = [];
$scope.update = function(rec){
var id = $scope.id;
$scope.upload = $upload.upload({
//url: 'api/manage_features/update/'+id, //upload.php script, node.js route, or servlet url
url: 'api/AdminArea/users/update/'+id,
method: 'POST',
headers: {'header-key': '83c238df1650bccb2d1aa4495723c63f07672ee8'},
withCredentials: true,
data:rec , //{data:rec},
//data: {name:$scope.name,price:$scope.price},
}).progress(function(evt) {
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function(data, status, headers, config) {
toaster.pop('success', 'Edit', 'Record Updated successfully.');
setTimeout(function(){ $state.go('app.manage_users'); }, 3000);
$scope.$root.$broadcast("myDocEventReload", {});
})
}
<div class="form-group">
<label class="col-lg-2 control-label">Role:</label>
<div class="col-lg-5">
<div ng-show="addForm.$submitted || addForm.Name.$touched">
<div ng-show="addForm.Name.$error.required" style="color:red;">Field required!.</div>
</div>
<select class="form-control input-sm" ng-model="rec.roles" name="Role">
<option ng-repeat="roles in user " ng-selected="{{rec.roles==user.Role}}" value="{{roles.Role}}" >{{roles.Role}}</option>
</select>
</div>
</div>