Unable to display WEBAPI data in Angularjs repeat directive - c#

Can somebody help in displaying webapi data in angularjs repeat directive in my first Angular application?
I'm getting data from the WEBAPI as expected like below
[{"FLAVOR_ID":"BES","FLAVOR_NAME":"BES"},{"FLAVOR_ID":"BUN","FLAVOR_NAME":"BUN"}]
API Controller:
public class ItemMaintenanceController : ApiController
{
ItemMaintenanceRepository itemRepository;
public ItemMaintenanceController(ItemMaintenanceRepository _itemRepository)
{
itemRepository = _itemRepository;
}
[HttpGet]
public IEnumerable<MA_Flavor> GetAllFlavors()
{
return itemRepository.GetAllFlavors();
}
}
Client.html:
<!DOCTYPE html>
<html>
<head>
<title> Client</title>
<script src="Scripts/angular.js"></script>
<script src="Scripts/angular-resource.js"></script>
<script>
alert("start");
var app = angular.module("myapp", ['ngResource']);
var controller = function ($scope, $resource) { // controller uses $resource, which is part of ngResource
$scope.flavor = {};
$scope.getFlavors = function () {
alert("calling getflvors");
var request = $resource("http://localhost:55762/api/ItemMaintenance/GetAllFlavors?Id=CMN");
$scope.flavor = request.query();
};
////$scope.clear = function () {
//// $scope.flavor = {};
//// $scope.error = "";
////}
$scope.getFlavors();
myapp.controller("ItemMaintenanceController", controller);
</script>
</head>
<body ng-app="contacts">
<div ng-controller="ItemMaintenanceController">
<select ng-model="flavor">
<option ng-repeat="fl in Flavor" value="{{fl.FLAVOR_NAME}}">{{fl.FLAVOR_NAME}}</option>
</select>
<h1>You selected: {{flavor.FLAVOR_NAME}}</h1>
</div>
</body>
</html>

Looks like issue with the names of the ng-controller, ng-module and ng-app. Try to change and hope it will work.
<body ng-app="contacts">
<div ng-controller="ItemMaintenanceController">
<Script>
var app = angular.module('contacts', []);
// To fetch all falvors
app.controller("ItemMaintenanceController", function ($scope, $http) {
.....
...
</script>

I think you're close. based on what you have I think something like this should work:
<select ng-model="selectedFlavorId">
<option ng-repeat="fl in flavor" value="{{fl.FLAVOR_ID}}">{{fl.FLAVOR_NAME}}</option>
</select>
your data is in $scope.flavor and I assume that if you debug it will look like this:
$scope.flavor = [{"FLAVOR_ID":"BES","FLAVOR_NAME":"BES"},{"FLAVOR_ID":"BUN","FLAVOR_NAME":"BUN"}]
you want the id in your value field as that is the bit you need to know which value you selected. the value you see in dropdown should be the name of the flavor.
when you select something, that value will be reflected in the model.
as I chose selectedFlavorId, you will find that populated under $scope.selectedFlavorId. Do not override your API data with the selected value like you've just done.
selectedFlavorId will give you the ID of the item you selected so you need a bit more code after this to get the name of that property from your data array.

There may following issues in your code.
Your angular modules defined as myapp and in ng-app you have used
contacts.
You have to create two different scope variables, one for the flavor
and another is flavors. flavors you need to use under the ng-options
and flavor you have to use for ng-model.
What I understood request.query() will return the resource object,
So have two options to get data from the query. More details about
the resource you can find here
var request = $resource("http://localhost:55762/api/ItemMaintenance/GetAllFlavors?Id=CMN");
Option 1
request.query(function(data) {
$scope.flavor = data;
});
Option 2
request.query().$promise.then(function(data) {
// success
$scope.flavor = data;
}, function(errResponse) {
// fail
});

Related

How to send json object to razor model then angularjs

This is the way I was sending my model to an angular controller scope.
c# Controller:
public class AreaMenuController : RootController
{
// GET: Menu
public PartialViewResult Index()
{
var mod = Modules.Instance.ModuleList.FirstOrDefault(m => m.Prefix.Equals(base.GetArea(), StringComparison.CurrentCultureIgnoreCase));
return PartialView("_AreaMenu", mod.ModuleMenus);
}
}
View cshtml:
#using Nuclei.Models
#model IEnumerable<Nuclei.Models.Menu>
<script type="text/javascript">
#{ var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); }
window.areaMenus = #Html.Raw(serializer.Serialize(Model));
</script>
<script type="text/javascript" src="#Url.Content("~/Scripts/AngularControllers/_AreaMenuController.js")"></script>
<div ng-controller="AreaMenuController as vm" ng-init="vm.initializeController()">
<div id="accordion" ng-class="accordian-menu" style="visibility: visible;">
<ul>
<li ng-repeat="menu in vm.areaMenus">
...
</li>
</ul>
</div>
</div>
Angular Js file:
var NucleiApp = angular.module('NucleiApp');
NucleiApp.controller('AreaMenuController', ['$scope', '$http', '$location', function ($scope, $http, $location) {
"use strict";
var vm = this;
vm.initializeController = function () {
vm.areaMenus = window.areaMenus;
}
}]);
Question 1: Is there a smoother way to send your c# model through to angular other than through global window object?
You can use an $http get from angular, however because this is processed client-side there is always a bit of lag before it gets displayed, because it needs to call the c# controller and get the data. So I'm reserving $http get for updates only.
The other other way I was thinking was to send the view a Json object straight off:
c# controller:
public class AreaMenusController : RootController
{
// GET: Menu
public PartialViewResult Index()
{
return PartialView("_AreaMenu", GetAreaMenus());
}
public JsonResult GetAreaMenus()
{
var mod = Modules.Instance.ModuleList.FirstOrDefault(m => m.Prefix.Equals(base.GetArea(), StringComparison.CurrentCultureIgnoreCase));
return Json(new { areaMenus = mod.ModuleMenus }, JsonRequestBehavior.AllowGet);
}
}
View cshtml:
#using System.Web.Mvc
#model JsonResult
<script type="text/javascript">
window.areaMenus = #Model;
</script>
Question 2: I'm not really sure how to initialize the #model at this point and send it through to the angular file and again, if there is a better option than javascripts global window object... open to suggestions!
We currently do this to bootstrap a set of data that is later updated by a call into a WebAPI.
The reason we do this is we have found cases where the data, when bootstrapped via an API call, was coming back too slowly, which gave a bad experience to our users.
In our razor view:
<html>
<head>
<script>
window.areaMenus = '#Html.Raw(Model.SerializedJsonString)';
</script>
</head>
</html>
Then when our angular app is Run(), we deserialize the data, and use it from there:
var app = angular.module('myApp', ["stuff"])
.run(["menuService", (menuService) => {
// deserialize the json string into my object
var areaMenus = angular.fromJson(window.areaMenus);
// do something with it
menuService.Load(areaMenus);
}]);
This'll get the data available to angular immediately without having to wait for a $http request to complete, which should address your issue.

Load specific data based on passed Id on link click in ASP.NET

My goal is to build AJAX, which will show details of specific Building when user clicks on specific link <a...>
My Controller
public IActionResult BuildingDetail(int id)
{
return PartialView("_BuildingDetailsPartial", _buildingRepository.GetById(id));
}
My view
#foreach (var employee in Model.employees)
{
...
<a id="LoadBuildingDetail" href="#LoadBuildingDetail" data-assigned-id="#employee.Office.BuildingId"
onclick="AssignButtonClicked(this)">#employee.Office.Name</a>
...
}
Place to show Details of Building when user clicks on link. So _BuildingDetailsPartial will render here.
<div id="BuildingDetail">
</div>
Scripts: Im stuck here. I need to load specific BuildingDetail based on passed id.
<script type="text/javascript">
$(document).ready(function () {
function AssignButtonClicked(buildingId) {
var BuildingId = $(buildingId).data('assigned-id');
}
$("#LoadBuildingDetail").click(function () {
$("#BuildingDetail").load("/employees/buildingdetail/", { id: AssignButtonClicked() }, );
});
})
</script>
The issue is due to the logic of the click handler in jQuery. You're attempting to call a function in the onclick attribute of the element which won't be accessible as it's defined inside the document.ready scope.
Also, you're trying to set the id property of the object you send in the request to a function which has no return value.
To fix this, remove the onclick attribute from the HTML you generate, and just read the data attribute from the element directly in the jQuery event handler before you send the AJAX request. Try this:
#foreach (var employee in Model.employees)
{
<a class="LoadBuildingDetail" href="#LoadBuildingDetail" data-assigned-id="#employee.Office.BuildingId">#employee.Office.Name</a>
}
<script type="text/javascript">
$(function () {
$(".LoadBuildingDetail").click(function () {
$("#BuildingDetail").load("/employees/buildingdetail/", {
id: $(this).data('assigned-id')
});
});
})
</script>

jQueryu ui autocomplete doesn´t show anything in MVC c#

I want to display an autocomplete textbox in a MVC C# View using jQuery-ui autocomplete, this is the code of my view
#{
ViewBag.Title = "Index";
}
<script src ="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript">
$(function () {
$("#SearchString").autocomplete({
source: "/Borrar/autocompletar",
minLength: 1,
select: function (event, ui) {
if (ui.item) {
$("#SearchString").val(ui.item.value);
}
}
});
});
</script>
<div class="container col-md-10 col-md-offset-3">
<h2>Autocompletar</h2>
#using (Html.BeginForm())
{
<p>
Empresa: #Html.TextBox("SearchString")
<input type="submit" value="Search" />
</p>
}
</div>
this is the code of the controller that should populate the textbox
public JsonResult autocompletar(string prefix)
{
List<GFC_Site.ViewModels.EmpresaAutocomplete> listado = new List<GFC_Site.ViewModels.EmpresaAutocomplete>();
ProxyGFC.ServiceGFCClient cliente = new ProxyGFC.ServiceGFCClient();
List<WcfService.Entidades.EmpresaAutocomplete> listadoBase = new List<WcfService.Entidades.EmpresaAutocomplete>();
listadoBase = cliente.Autocompletar(prefix);
foreach (var item in listadoBase)
{
GFC_Site.ViewModels.EmpresaAutocomplete dato = new ViewModels.EmpresaAutocomplete();
dato.empresa = item.empresa;
//dato.np = item.np;
listado.Add(dato);
}
return Json(listado, JsonRequestBehavior.AllowGet);
}
where (GFC_Site.ViewModels.EmpresaAutocomplete) is a class with only one string property (empresa) and (ProxyGFC.ServiceGFCClient cliente) is a connection to a WCF Server, the WCF is the one that connects the application with the database and (List listadoBase) is a class in WCF with two properties(empresa and np).
and this is the method in WCF that retrieve the info that I want to display in the textbox
public List<EmpresaAutocomplete> Autocompletar(string prefix)
{
OdbcCommand cmd = Helper.Commandos.CrearComando();
cmd.CommandText = "select numero_patronal, nombre_empresa from empresas where estado= ? and nombre_empresa like ?";
cmd.Parameters.Add("#estado", OdbcType.VarChar).Value = "1";
cmd.Parameters.AddWithValue("#empresa", prefix + "%");
List<EmpresaAutocomplete> data = new List<EmpresaAutocomplete>();
try
{
cmd.Connection.Open();
var reader = cmd.ExecuteReader();
while (reader.Read())
{
EmpresaAutocomplete datos = new EmpresaAutocomplete();
datos.np = reader["numero_patronal"].ToString();
datos.empresa = reader["nombre_empresa"].ToString();
data.Add(datos);
}
}
catch (Exception ex)
{
throw new ApplicationException("Excepcion :", ex);
}
return data;
}
well, my problem is that the textbox doesn´t show anything, actually it gets frozen
could you please tell me what seems for you to be the problem?
First off, let’s take take a look at autocomplete in action, starting with a text input:
<label for=”somevalue”>Some value:</label><input type=”text” id=”somevalue” name=”somevalue”/>
If we add a reference to the jQuery UI script file and css file, we can add a script block to our view:
<script type=”text/javascript” language=”javascript”>
$(document).ready(function () {
$(‘#somevalue’).autocomplete({
source: ‘#Url.Action(“Autocomplete”)’
});
}) </script>
This script block identifies the text input by id and then invokes the autocomplete function to wire up the autocomplete behaviour for this DOM element. We pass a URL to identify the source of the data. For this post I’ve simply created an ASP.NET MVC action that returns JSON data (shown below). Note that in the view I used Url.Action to look up the URL for this action in the routing table – avoid the temptation to hard-code the URL as this duplicates the routing table and makes it hard to change your routing later.
public ActionResult Autocomplete(string term)
{
var items = new[] {“Apple”, “Pear”, “Banana”, “Pineapple”, “Peach”};
var filteredItems = items.Where(
item => item.IndexOf(term, StringComparison.InvariantCultureIgnoreCase) >= 0
);
return Json(filteredItems, JsonRequestBehavior.AllowGet);
}
https://blogs.msdn.microsoft.com/stuartleeks/2012/04/23/asp-net-mvc-jquery-ui-autocomplete/

Asp.net MVC populate a list box with JQuery?

I have a list of Payees in a drop down box on my form. I would like to populate a different drop down, based on the selected item of the Payee drop down, without post backs and all that.
So, I created a method in my controller that does the work:
private JsonResult GetCategories(int payeeId)
{
List<CategoryDto> cats = Services.CategoryServices.GetCategoriesByPayeeId(payeeId);
List<SelectListItem> items = new List<SelectListItem>();
foreach(var cat in cats)
{
items.Add(new SelectListItem {Text = cat.Description, Value = cat.CategoryId.ToString()});
}
return Json(items);
}
Now, I am unsure what to add to my view to get this to work.
At the moment, all I have is this:
<% using (Html.BeginForm())
{%>
<p>
<%=Html.DropDownList("SelectedAccountId", Model.Accounts, "Select One..", null) %>
</p>
<p>
<%=Html.DropDownList("SelectedPayeeId", Model.Payees, "Select One...", null) %>
</p>
<input type="submit" value="Save" />
<%
}%>
they populate fine... so when the user selects the SelectedPayeeId drop down, it should then populate a new (Yet to be created?) drop down which holds categories, based on the SelectedPayeeId.
So, I think I need to create a JQuery function (Never done JQuery.. so not even sure where it goes) which monitors the Payee drop down for an onChange event? And then call the method I created above. Does this sound right, and if so, can you guide me in how to achieve this?
Your reasoning so far is totally sound. First you are going to want to include the jquery library in your View / Master. You can download a copy of jquery from http://jquery.com/. Add the file to you project and include a <script src="/path/to/jquery.js"> to the <head> of your document. You are going to want to add another dropdown to your View (and probably another property to your model). We'll call this 'SelectedCategoryId:'
<%=Html.DropDownList("SelectedCategoryId", null, "Select One...", new { style = "display:none;"}) %>
We've set the style of this Drop Down to not be visible initially because there is nothing to select inside of it. We'll show it later after we generate some content for it. Now, somewhere on your page you will want to include a <script> block that will look something like this:
$(document).ready(function() { $('#SelectedPayeeId').change(function() {
$.ajax({
type: 'POST',
url: urlToYourControllerAction,
data: { payeeId: $(this).val() },
success: function(data) {
var markup = '';
for (var x = 0; x < data.length; x++ ) {
markup += '<option value="' + data[x].Value + '">'+data[x].Text+'</option>';
}
$('#SelectedCategoryId').html(markup).show();
}
}); }); });
This code binds the anonymous function written above to the DOM element with the ID of 'SelectedPayeeId' (in this case your dropdown). The function performs an AJAX call to the url of your method. When it receives the results of the request (your JSON you returned) we iterate over the array and build a string of the html we want to inject into our document. Finally we insert the html into the 'SelectedCategoryId' element, and change the style of the element so it is visible to the user.
Note that I haven't run this code, but it should be (almost) what you need. jQuery's documentation is available at http://docs.jquery.com/Main_Page and the functions I used above are referenced here:
.ready()
.change()
jQuery.ajax()
.html()
.show()
You'd need to make the GetCategories as a public method as it would correspond to an action handler in your controller.
Your jquery code can look like:
<script type="text/javascript">
$(function() {
$('#SelectedPayeeId').change(function() {
$.get('<%= Url.Action("GetCategories", "YourControllerName") %>',
{payeeId: $(this).val()},
function(data) {
populateSelectWith($("#Category"), data);
});
});
//Place populateSelectWith method here
});
</script>
The populateSelectWith can fill your dropdown with data like:
function populateSelectWith($select, data) {
$select.html('');
$select.append($('<option></option>').val('').html("MYDEFAULT VALUE"));
for (var index = 0; index < data.length; index++) {
var option = data[index];
$select.append($('<option></option>').html(option));
}
}
I have not tested this code, but I am hoping it runs okay.
You can find syntax for the jquery ajax get here
Since you are not posting any data to the server, you can might as well decorate your controller action with a [HttpGet] attribute

ASP.NET MVC & JQuery Dynamic Form Content

I would like to dynamically add fields to an ASP.NET MVC form with JQuery.
Example:
<script language="javascript" type="text/javascript">
var widgets;
$(document).ready(function() {
widgets = 0;
AddWidget();
});
function AddWidget() {
$('#widgets').append("<li><input type='text' name='widget" + widgets + "'/></li>");
widgets++;
}
</script>
<ul id="widgets">
</ul>
This works, but I was going to manually iterate the form values in the controller:
[AcceptVerbs("Post")]
public ActionResult AddWidget(FormCollection form)
{
foreach (string s in form)
{
string t = form[s];
}
return RedirectToAction("ActionName");
}
But it occurred to me when I send the user back to the Get Action in the Controller I will have to set the FormData with the values entered and then iteratively add the widgets with <% scripting.
What is the est way to do this in the current release (5 I believe)?
My solution could be something like this (pseudo-code):
<script language="javascript" type="text/javascript">
var widgets;
$(document).ready(function() {
widgets = 0;
<% for each value in ViewData("WidgetValues") %>
AddWidget(<%= value %>);
<% next %>
});
function AddWidget( value ) {
$('#widgets').append("<li><input type='text' name='widget" + widgets +
"'>" + value + "</input></li>");
widgets++;
}
</script>
<ul id="widgets">
</ul>
And in the controller:
[AcceptVerbs("Post")]
public ActionResult AddWidget(FormCollection form)
{
dim collValues as new Collection;
foreach (string s in form)
{
string t = form[s];
collValues.add( t )
}
ViewData("WidgetValues") = collValues;
return RedirectToAction("ActionName");
}
You can work out the details later
(sorry for mixing VB with C#, I'm a VB guy)
i might be missing the point here, but, do you need to actually post the data back to the controller via a form action? why not make an ajax call using jquery to post the data to the controller...or better yet a web service? send the data async and no need to rebuild the view with the data values sent in.
This works fine if the values are being consumed and never used again, however, if you plan on persisting the data and surfacing it through a the view, your model should really support the data structure. maybe a Dictionary<string, string> on the model.
I'm not a ASP.net developer but I know from PHP that you can use arrays as names for input fields
Ex:
<input type="text" name="widgets[]" />
<input type="text" name="widgets[]" />
You can then iterate through the post variable widgets as if it was an array of values.
No messing around with dynamicaly named variables etc.
As far as I understand the problem is to preserve the posted values in widgets.
I thik you can just render those widgest you wont to populate on the server during the View rendering.

Categories