How to get the values of the child element from the parent element in angularjs - angularjs

I have two database tables with one being the parent and the other being the child. The parent table has a reference to the child table. Database table was generated using code-first approach with the data models are below:
[Table("Family")]
public partial class Family
{
public int Id { get; set; }
public string Surname { get; set; }
public string FirstName { get; set; }
public int RoleId { get; set; }
public int FuId { get; set; }
public int RiskAreaId { get; set; }
public int LocationId { get; set; }
public DateTime CreatedDate { get; set; }
[ForeignKey("RoleId")]
public virtual Role Role { get; set; }
[ForeignKey("FuId")]
public virtual FamilyUnit FamilyUnit { get; set; }
[ForeignKey("RiskAreaId")]
public virtual RiskArea RiskArea { get; set; }
[ForeignKey("LocationId")]
public virtual Location Location { get; set; }
}
And the FamilyUnit table i below:
[Table("FamilyUnit")]
public partial class FamilyUnit
{
public int Id { get; set; }
[Column(TypeName = "varchar")]
[StringLength(50)]
[Required]
public string FamilyUnitName { get; set; }
public virtual IEnumerable<Family> Families { get; set; }
}
I then created a webAPI project so my project can consume the APIs. My Api is shown below:
[EnableCors("*", "*", "*")]
public class FamilyUnitController : ApiController
{
FamilyUnitBs familyUnitObjBs;
public FamilyUnitController()
{
familyUnitObjBs = new FamilyUnitBs();
}
[ResponseType(typeof(IEnumerable<FamilyUnit>))]
public IHttpActionResult Get()
{
var famUnits = familyUnitObjBs.GetALL();
return Ok(famUnits);
}
[ResponseType(typeof(FamilyUnit))]
public IHttpActionResult Get(int id)
{
FamilyUnit familyUnit = familyUnitObjBs.GetByID(id);
if (familyUnit != null)
return Ok(familyUnit);
else
return NotFound();
}
[ResponseType(typeof(FamilyUnit))]
public IHttpActionResult Delete(int id)
{
FamilyUnit familyUnit = familyUnitObjBs.GetByID(id);
if (familyUnit != null)
{
familyUnitObjBs.Delete(id);
return Ok(familyUnit);
}
else
{
return NotFound();
}
}
}
I then created another project called for the front-end of the application to consume the API methods.
Below is the angularjs controller with the factory service
appEIS.factory('familyMgmtService', function ($http,$rootScope) {
famMgmtObj = {};
famMgmtObj.getAll = function () {
var Fams;
Fams = $http({ method: 'Get', url:$rootScope.ServiceUrl+ 'FamilyUnit' }).
then(function (response) {
return response.data;
});
return Fams;
};
famMgmtObj.createFamily = function (fam) {
var Fam;
Fam = $http({ method: 'Post', url:$rootScope.ServiceUrl+ 'Family', data: fam }).
then(function (response) {
return response.data;
}, function(error) {
return error.data;
});
return Fam;
};
famMgmtObj.deleteFamilyById = function (eid) {
var Fams;
Fams = $http({ method: 'Delete', url:$rootScope.ServiceUrl+ 'FamilyUnit', params: { id: eid } }).
then(function (response) {
return response.data;
});
return Fams;
};
famMgmtObj.getFamilyByFuId = function (fid) {
var Fams;
console.log(fid);
Fams = $http({ method: 'Get', url: $rootScope.ServiceUrl + 'Family', params: { id: fid } }).
then(function (response) {
return response.data;
});
return Fams;
};
return famMgmtObj;
});
appEIS.controller('familyMgmtController', function ($scope, familyMgmtService, utilityService, $window) {
$scope.Sort = function (col) {
$scope.key = col;
$scope.AscOrDesc = !$scope.AscOrDesc;
};
familyMgmtService.getAll().then(function (result) {
$scope.Fams = result;
console.log(result);
});
$scope.CreateFamily = function (Fam, IsValid) {
if (IsValid) {
$scope.Fam.Password = utilityService.randomPassword();
familyMgmtService.createFamily(Fam).then(function (result) {
if (result.ModelState == null) {
$scope.Msg = " You have successfully created " + result.FamilyId;
$scope.Flg = true;
utilityService.myAlert();
$scope.serverErrorMsgs = "";
familyMgmtService.getAll().then(function (result) {
$scope.Fams = result;
});
}
else {
$scope.serverErrorMsgs = result.ModelState;
}
});
}
};
$scope.DeleteFamilyById = function (Fam) {
if ($window.confirm("Do you want to delete Family with Id:" + Fam.FamilyId + "?")) {
familyMgmtService.deleteFamilyById(Fam.FamilyId).then(function (result) {
if (result.ModelState == null) {
$scope.Msg = " You have successfully deleted " + result.FamilyId;
$scope.Flg = true;
utilityService.myAlert();
familyMgmtService.getAll().then(function (result) {
$scope.Fams = result;
});
}
else {
$scope.serverErrorMsgs = result.ModelState;
}
});
}
};
$scope.GetFamilyByFuId = function (Fam) {
familyMgmtService.getFamilyByFuId(Fam.fid).then(function (result) {
console.log(result);
$scope.Fams = result;
});
};
$scope.CreateMultiFamily = function () {
var file = $scope.myFile;
var uploadUrl = "http://localhost:60736/api/Upload/";
utilityService.uploadFile(file, uploadUrl, $scope.eid).then(function (result) {
$scope.image = result;
});
};
});
The family unit is displaying well in an accordion list but the various families are not getting displayed using the familyUnit Id as shown below:
<div class="panel-body">
<div dir-paginate="emp in Fams | filter:search | orderBy:key:AscOrDesc | itemsPerPage:10" class="wrapper center-block">
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading{{emp.Id}}">
<h4 class="panel-title">
<div role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{emp.Id}}" aria-expanded="true" aria-controls="collapse{{emp.Id}}">
{{emp.FamilyUnitName}}
</div>
</h4>
</div>
<div id="collapse{{emp.Id}}" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="heading{{emp.Id}}">
<div class="panel-body">
<div ng-repeat="f in emp.Families">{{f.FirstName}} - {{f.Surname}}</div>
</div>
</div>
</div>
</div>
</div>

Based on the discussion in the comments, this issue looks like the issue with data and not with the front-end (yet).
You need to load the Families details while getting the FamilyUnit in your Get(int id) method. There are two ways through which you can do the early loading.
Use Include with Linq, like:
var familyUnit = familyUnitObjBs.FamilyUnits
.Include(fu => fu.Families)
.Where (fu +. fu.Id == Id)
.ToList();
The second option could be using the early loading by removing the virtual from your data structure, which might be an issue if you plan to add more methods or maybe if you have test cases to override, still, it will look like:
[Table("FamilyUnit")]
public partial class FamilyUnit
{
public int Id { get; set; }
[Column(TypeName = "varchar")]
[StringLength(50)]
[Required]
public string FamilyUnitName { get; set; }
public IEnumerable<Family> Families { get; set; }
}
You can find more details about lazy loading and early loading at:
https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx
EDIT:
1. You can use strong type instead of var for familyUnit:
List<FamilityUnit> familyUnit= familyUnitObjBs.FamilyUnits
.Include(fu => fu.Families)
.Where (fu +. fu.Id == Id)
.ToList();
Get the list instead of FirstOrDefault() if you need whole list:
return db.Familiies.Where(x => x.FuID == id).ToList();

Related

POST dynamically added Lists to Controller as Json and redirect view

Description
I'm am creating a dynamic table where the user can select regions in a dropdown lists. On "add" the user can also add new table rows with region dropdown lists included. On POST, a list of Regions should be posted to the controller where it´s being saved to the SavingPlan model.
Problem
Ajax is returning null to my controller even though I have saved selected option-data to string arrays which is being posted to the controller.
Addition
I am fairly new to ASP.NET MVC so please have that in mind when commenting. I am open minded towards doing things differently but I´d very much appreciate I someone would be able to guid me and my code in the right direction.
Region Model
public class Region
{
public int Id { get; set; }
public string Name { get; set; }
}
Saving Plan Model
public SavingPlan()
{
}
public SavingPlan(List<Region> regionList)
{
RegionList = regionList;
}
public int Id { get; set; }
public ApplicationUser AssessmentUser { get; set; }
public IEnumerable<Region> RegionLookUp { get; set; }
public bool IsActive { get; set; }
public byte RegionId { get; set; }
public Region Region { get; set; }
public List<Region> RegionList { get; set; }
}
SavingPlan - ViewModel
public class SavingPlan
{
public SavingPlan()
{
}
public SavingPlan(List<Region> regionList)
{
RegionList = regionList;
}
public int Id { get; set; }
public ApplicationUser AssessmentUser { get; set; }
public IEnumerable<Region> RegionLookUp { get; set; }
public bool IsActive { get; set; }
public byte RegionId { get; set; }
public Region Region { get; set; }
public List<Region> RegionList { get; set; }
}
Controller Action GET - NewSavingPlan
public ActionResult NewSavingPlan()
{
SavingPlanAssessmentView viewModel = new SavingPlanAssessmentView();
viewModel.SavingPlan = new SavingPlan();
var regions = _context.Regions
.ToList();
viewModel.RegionLookUp = regions;
return View(viewModel);
}
Controller Action POST - Save SavingPlan
[HttpPost]
public JsonResult SaveList(string RegionList)
{
var urlBuilder = new UrlHelper(Request.RequestContext);
var url = urlBuilder.Action("Index", "Assessments");
string[] arr = RegionList.Split(',');
foreach (var item in arr)
{
var region = item;
}
return Json(new { status = "success", redirectUrl = Url.Action("Index","Home") });
}
SavingPlan Partial View
#model BBRG.ViewModels.SavingPlanAssessmentView
<h2>#Model.Heading</h2>
#*#using (Html.BeginForm("Save", "Assessments", FormMethod.Post))
{*#
#*#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Id)*#
<legend>Saving Plan</legend>
<table id="regionTable" class="table table-striped">
<thead>
<tr>
<td>Region</td>
<td> <button id="add" type="button" class="btn btn-link">Add</button></td>
<td></td>
</tr>
</thead>
<tbody>
<tr id="regionRow_1">
<td>
#Html.DropDownListFor(m => m.RegionId, new SelectList(Model.RegionLookUp, "Id", "Name"), "Select Region", new { #class = "form-control Region", id = "Region_1", type="string", name = "Region", selected="false" })
</td>
<td>
<button data-region-id="#Model.RegionId" id="deleteRegion" type="button" class="btn btnDeleteRegion btn-link btn-xs btn" btn-xs>remove</button>
</td>
</tr>
</tbody>
</table>
<hr />
<p>
#Html.HiddenFor(m => m.Id)
<button data-saving-id="#User.Identity" onclick="saveRegion()" type="submit" calss="btn btn-default js-toggle-save">Save</button>
</p>
Jquery - Add new table row with dropdownlist
$(document).ready(function () {
var counter = 2;
$(function () {
$('#add').click(function () {
$('<tr id="regionRow_' + counter + '">'
+ '<td>'
+ '<select type="text" value="RegionId" name="Region" id="Region_'+ counter+'" class="form-control Region" " >'
+ $(".Region").html()
+ '</select>'
+ '</td>'
+ '<td>'
+ '<button data-region-id= id="deleteRegion" type="button" class="btn btnDeleteRegion btn-link btn-xs btn" btn-xs>remove</button>'
+ '</td>'
+ '</tr>').appendTo('#regionTable');
counter++;
return false;
});
});
});
Jquery and .ajax for POST
{
<script src="~/Scripts/SavingPlanScripts.js"></script>
<script>
var saveRegion = (function () {
var array = [];
var commaSeperated = "";
var count = 1;
$("#regionTable tbody .Region").each(function (index, val) {
var regionId = $(val).attr("Id");
var arr = regionId.split('_');
var currentRegionId = arr[1];
var isSelected = $(".Region option").is(':selected', true);
if (isSelected) {
array.push(currentRegionId);
}
count++;
});
if (array.length != 0) {
commaSeperated = array.toString();
$.ajax({
type: "POST",
dataType: "json",
contentType: "/application/json",
url: "/SavingPlans/SaveList",
data: { "RegionList": commaSeperated },
success: function (json) {
if (json.status == "success") {
window.location.href = json.redirectUrl;
};
}
});
};
});
</script>
}```
I found the solution to my problem, I forgot to stringify my .ajax data. If anyone still want to provide me with some constructive input, please don´t hesitate.
$.ajax({
url: "../SavingPlans/SaveList",
data: JSON.stringify({ RegionId: commaSeperated }),
type: "POST",
dataType: "json",
contentType: 'application/json; charset=utf-8',
success: function (json) {
if (json.status == "success") {
window.location.href = json.redirectUrl;
};
}
});

Get attributes associated with a selected item in a drop down list AngularJS

I'm building an app using ASP.NET Web API with AngularJS and I'm new to these frameworks. I have a drop down list which display data from the API. When I select an element from the drop down, I want to get the other attributes associated with it.
Here's the API
[Route("CustomerRecords")]
public List<Customer> Get()
{
return new List<Customer>()
{
new Customer { CID=1, Name="Bruce Wayne", PIN="1234", Bal=1000000, cardStatus= 0 }
,new Customer { CID=2, Name="Tony Stark", PIN="2246", Bal=900000, cardStatus= 0 }
,new Customer { CID=3, Name="Jon Snow", PIN="2398", Bal=3000, cardStatus= 1 }
,new Customer { CID=4, Name="Rustin Cohle", PIN="7549", Bal=450000, cardStatus= 2 }
};
}
}
public class Customer
{
public int CID { get; set; }
public string Name { get; set; }
public string PIN { get; set; }
public int Bal { get; set; }
public int cardStatus { get; set; }
}
here's the module, the service and the factory method
var customerAppModule = angular.module("customerApp", []);
customerAppModule.controller('CustomerCtrl', function ($scope, CustomerService)
{
getCustomerRecords();
function getCustomerRecords() {
CustomerService.getCustomers()
.success(function (data) {
console.log(data);
$scope.customers = data;
})
.error(function (data, status) {
console.error('failure loading the customer record', status, data);
$scope.customers = {};
});
}
});
customerAppModule.factory('CustomerService', ['$http', function ($http) {
var customerService = {};
var urlBase = 'http://localhost:51701/Customer';
customerService.getCustomers = function () {
return $http.get(urlBase + '/CustomerRecords');
};
return customerService;
}]);
and here is my drop down
<select ng-change="getCustomers(details)" ng-model="details">
<option ng-repeat="customer in customers" value="{{customer.CID}}">{{customer.Name}}</option>
</select>
So, only the names appear in my drop down, but if I select a particular name, I want to be able to get its other attributes
Your function getCustomers inside the controller should have all the details as a parameter, since you are passing it,
$scope.getCustomers = function(details){
//this has all the details associated with id (details);
}
use select.js library and try like following
<ui-select ng-model="model" append-to-body="true">
<ui-select-match>
<span ng-bind="$select.selected.name"></span>
</ui-select-match>
<ui-select-choices repeat="item in modelList" >
<div ng-bind="item.name" ng-click="selectValue(item)"></div>
</ui-select-choices>
</ui-select>

"Movie" Model taking "Name" property of internal object "Actors"

I am new to Angular and Entity framework.
Here is the code from my AngularJS controller:
$scope.add = function () {
$scope.loading = true;
alert(this.newMovie.Name);
debugger;
$http.post('api/Movie/', this.newMovie).then(function onSuccess(response) {
alert("Added Successfully!!");
debugger;
$scope.showAddMovieForm = false;
$scope.movies.push(response);
$scope.loading = false;
}).catch(function (response) {
$scope.error = "An Error has occured while adding movie! :(" + response.data;
$scope.loading = false;
});
};
Here is how the Action method looks in my MovieController in MVC:
public HttpResponseMessage Post(Movie movie)
{
if (ModelState.IsValid)
{
// _db.People.Where(na => movie.Actors.Any(a => a.PersonId == na.PersonId));
_db.Movies.Add(movie);
_db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, movie);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { movieId = movie.MovieId }));
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
Movie Model Class:
public partial class Movie
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Movie()
{
this.Actors = new HashSet<Person>();
}
public int MovieId { get; set; }
public string Name { get; set; }
public Nullable<short> YearOfRelease { get; set; }
public string Plot { get; set; }
public byte[] Poster { get; set; }
public Nullable<int> ProducerId { get; set; }
public virtual Person Producer { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Person> Actors { get; set; }
}
When I put a debugger in the JS code I can see that Angular is passing the object in correct format.
But somehow when it reaches Action, the "Movie" model takes "Name" property value "Actors" object which is part of "Movie" itself.
Not able to understand why "Movie" model is getting the "Name" property of "Actors".
You need to fix the way you are creating your Actors object in Movie object.
Actor should be JS Array of objects and your Movie object should look like below when you debug:
But, in your case Actors is just a single object. Hope it helps.

System.NullReferenceException in controller ASP.Net MVC

Working with (simple bowling game web app) where there are two text boxes and one submit button.
text box 1 = FirstRoll ,text box 2 = SecondRoll
User enter two numbers and cilck submit button then displays a score.
Issue : Getting System.NullReferenceException in Submit action method. Why frame is empty in first instance?
Controller
[HttpPost]
public JsonResult Submit(Frame[] _frames)
{
int result= 0;
var objBowlingScore = new GameEngineService();
foreach(var frame in _frames)
{
result = objBowlingScore.CalculateFrameScore(frame);
}
return Json(objBowlingScore);
}
Model
server side check validations are removed for code readability
public class Frame
{
public int FrameId { get; set; }
public int FirstRoll { get; set; }
public int SecondRoll { get; set; }
public int ThirdRoll { get; set; }
public int Score { get; set; }
}
View
<p>1st Roll: #Html.EditorFor(m => m.FirstRoll)</p>
<p>2nd Roll: #Html.EditorFor(m => m.SecondRoll)</p>
<button id="submitButton" class="btn btn-primary btn-lg">Submit Score</button>
<p><label>The current frame is : </label><label id="lblFrameCount"></label></p>
<p><label>The current score is : </label><label id="lblTotalScore"></label></p>
#section DocumentReady {
<script type="text/javascript">
var bowlingData = { "frames": [] };
$('#submitButton').click(function (e) {
var temp = {
"firstroll": $("#FirstRoll").val(),
"secondroll": $("#SecondRoll").val()
};
bowlingData.frames.push(temp);
var element = this;
$.ajax({
url: "/Home/Submit",
type: "POST",
data: JSON.stringify(bowlingData),
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function (data) {
$("#lblTotalScore").text(data.Score);
$("#FirstRoll").val("");
$("#SecondRoll").val("");
},
error: function () {
alert("An error has occured!!!");
}
});
});
</script>
Service
....
public int CalculateFrameScore(Frame _frame)
{
return _frame.FirstRoll + _frame.SecondRoll + _frame.ThirdRoll;
}
....
The issue was the parameter name in the Submit method didn't match with the parameter used in the jQuery event handler.
_frames should be frames. (i.e.
Was
public JsonResult Submit(Frame[] _frames))
Should be
public JsonResult Submit(Frame[] frames))

I just want to pass the list to the asp.net web api using angularjs

I'm working on EAV database pattern.
My model is like this:
public class LeadsModel
{
public int? CompId { get; set; }
public int LeadID { get; set; }
public string LeadName { get; set; }
public string source { get; set; }
public string status { get; set; }
public int UserId { get; set; }
[Required]
public List<AttributesModel> AList { get; set; }
}
My view is like this. In view I'm fetching the list of attributes and I want to post back the using angularjs.
<div class="form-group" ng-repeat="At in Attributes" >
<label for="{{At.Attri}}" class="col-md-4 control-label">{{At.Attri}}</label>
<div class="col-md-8">
#*<input type="hidden" name="{{At.AID}}" data-ng-model="newLead.NewAlist" />*#
<input type="text" class="form-control" id="{{At.Attri}}" name="{{At.Attri}}" pl placeholder="Enter {{At.Attri}}" data-ng-model="newLead.AList.AttriValue" ng-blur="AddItemToList(newLead.Alist.AttriValue)" />
</div>
</div>
My Angular code is like this
$scope.add = function ()
{
$scope.loading = true;
this.newLead.AList = $scope.listt;
$http.post('/api/Leads/Posttbl_Lead', this.newLead).success(function (data) {
alert("Added Successfully!!");
$scope.loading = false;
$scope.addLMode = false;
})
.error(function () {
$scope.error = "An Error has occured while loading posts!";
$scope.loading = false;
});
}
and my web api controller is like this
public IHttpActionResult Posttbl_Lead(LeadsModel tbl_Lead)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
tbl_Lead newLead = new tbl_Lead();
newLead.LeadName = tbl_Lead.LeadName;
newLead.source = tbl_Lead.source;
newLead.status = tbl_Lead.status;
newLead.LeadName = tbl_Lead.LeadName;
newLead.CompId = tbl_Lead.CompId;
db.tbl_Lead.Add(newLead);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = tbl_Lead.LeadID }, tbl_Lead);
}
Use this code to post your newLead of AngularJs to tbl_Lead of your API contoller. This is the complementary link for You to pass the list/ array object to You API.
$http({
contentType: "application/json; charset=utf-8",//required
method: "POST",
url: '/api/Leads/Posttbl_Lead',
dataType: "json",//optional
data:{ "tbl_Lead": newLead },
async: "isAsync"//optional
})
.success( function (response) {
alert('Saved Successfully.');
})
.error(function () {
$scope.error = "An Error has occured while loading posts!";
$scope.loading = false;
});
Edit-1
Below mentioned is the way to send AList inside LeadsModel to your api.
LeadsModel to send onto the server via API.
{
CompId=compId,
LeadID=leadID,
AList=[{FirstObject=firstObject},{SecondObject=secondObject}]
}

Resources