I've been trying to sort table data on click (ng-click if i use angularJS)
I'm getting data from database.I only need Sort functionality, if it happens through angularJs I would be very happy
Here it is what i did till now, I haven't done much as I'm new to AngularJS
#model WebApplication3.Models.StudentModel
#{
ViewBag.Title = "Index";
}
<h2>Students</h2>
<div><button class="create btn btn-success"><span class="glyphicon glyphicon-plus"></span> Create New</button></div>
<br/>
<table class="table" ng-app="StudentApp">
<tbody ng-controller="StudentCtrl">
<tr>
<th>Key</th>
<th ng-click="">First Name</th>
<th ng-click="">Last Name</th>
<th>Profile picture</th>
<th>Options</th>
</tr>
#foreach (var student in Model._StudentList)
{
<tr>
<td>#student.StudentID</td>
<td>#student.FirstName</td>
<td>#student.LastName</td>
<td>
<a class="example-image-link" href="~/Images/#student.PhotoURL" data-lightbox="example-set" data-title="#student.FirstName #student.LastName profile Picture"><img class="example-image" width="60" height="40" src="~/Images/#student.PhotoURL" alt="" /></a>
</td>
<td>
<span class="glyphicon glyphicon-pencil img-rotate" title="Edit"></span>
<span class="glyphicon glyphicon-exclamation-sign img-rotate" title="Infomation"></span>
<span class="glyphicon glyphicon-remove img-rotate" title="Remove"></span>
</td>
</tr>
}
</tbody>
</table>
I need to sort firstName, LastName when they click on respective th tag
Thanks
There is a sort table filter in AngularJS, which his name is OrderBy (documentation)
Currently, you cannot use that with your code, because OrderBy filter only works if AngularJS writes himself the table.
Example :
<table class="friend">
<tr>
<th>
Name
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
</th>
<th>
Phone Number
<span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
</th>
<th>
Age
<span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
</th>
</tr>
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>
</table>
In your case, the table is written in the view, and I think the only way to do it now with your code, is using a jQuery plugin.
Sadly, you loose the power of AngularJS...
Solution :
A solution would be to use ng-init attribute :
<div ng-app="" ng-init="names=[
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},
{name:'Kai',country:'Denmark'}]">
<ul>
<li ng-repeat="x in names">
{{ x.name + ', ' + x.country }}
</li>
</ul>
</div>
And you can use names variable in your controller, like :
console.log($scope.names); // Display the names
oh thats so sad, can i bind my MVC Model data to AngularJs
I mean like we bind JSON data
var app = angular.module('studentApp', []);
app.controller('StudntCtrl', function($scope, $http) {
htp.get('Student.json').success(function(data){
$scope.People = data;
});
});
like wise can i bind MVC model data to $scope.People ???
Related
I Have a table, there i have a details hyperlink on click of which i m showing a new table on same page in other div. The details Hyperlink has 3 input parameters based on which a service method gets triggered and I get data in the data. Now i have this task to show the 2nd grid on a new page. I m not sure how to do it.
Please help.
<table class="table table-bordered table-condensed table-hover ">
<thead>
<tr style="white-space: nowrap;">
<th>Date</th>
<th>Organization No</th>
<th>Contract No</th>
<th>Company Name</th>
<th>Plan No</th>
<th>Status</th>
<th>View Detail</th>
</tr>
</thead>
<tr ng-repeat="mas in vm | startFrom:currentPage*pageSize | limitTo:pageSize" data-ng-class="{active1:$index==selectedRow}" data-ng-click="rowHighilited($index)">
<td>{{mas.startDate | amDateFormat:'YYYY-MM-DD'}} </td>
<td>{{mas.organizationNumber}}</td>
<td>{{mas.contractNumber}} </td>
<td>{{mas.name}}</td>
<td>{{mas.planNumber}} </td>
<td>{{mas.description}} </td>
<td><span>Details</span></td>
</tr>
</table>
//getErrorDetailBySearch(mas.productAccountOid,mas.planNumber,mas.migrationRunID)it calls the function to bring data an binds it to the below div.//
<div ng-show="IsVisible">
<div ng-show="vm1.length > 0 && !loading">
<h2>Error Detail</h2>
<br />
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12 table-responsive">
<table class="table table-bordered table-condensed table-hover table-striped">
<thead>
<tr style="white-space: nowrap;">
<th>Contract Number</th>
<th>Plan Number</th>
<th>Business Error Message</th>
<th>System Error Details</th>
</tr>
</thead>
<tr ng-repeat="mas in vm1">
<td>{{mas.contractNumber}} </td>
<td>{{mas.planNumber}} </td>
<td>{{mas.businessErrorMsg }} </td>
<td>{{mas.systemErrorMsg}} </td>
</tr>
</table>
</div>
</div>
I am able to call a new page Called as ErrorDeatils but i dont know how to pass data b/w the pages.
This is controller written for 1st page
$scope.getErrorDetailBySearch = function (productAccountOid, planNr, migrationrunid) {
var path = "/Utilities/Error";
$location.path(path.replace(/\s+/g, ""));
};
var onSuccess = function (response) {
$scope.vm1 = response;
if ($scope.vm1 < 1) {
messageService.noDataFound();
}
}
$scope.getErrorDetailBySearch = function (productAccountOid, planNr,migrationrunid, skipFormValidate) {
if (skipFormValidate || b360FormsService.validateForm($scope.ViewErrorDetail)) {
errorService.globalproductAccountOid = productAccountOid;
errorService.globalplanNr = planNr;
errorService.globalmigrationrunid = migrationrunid;
$scope.loading = true;
repositoryService.getErrorDetailBySearch(productAccountOid, planNr, migrationrunid).$promise.then(onSuccess, onError).finally(function () {
$scope.loading = false;
});
}
}
Hi you can pass data both as query parameters or route params
Query Parameters
Lets say you have path "/errorDetails" and you want to pass "param" with value "10", then you can use $location.path() as follows:
$location.path("/errorDetails").search({param: 10});
and you can access value of "param" on resultant page's controller as:
$location.search().param;
Route Parameters
For using route params you will need to change your route configurations and you path will be like:
$routeProvider
.when('/errorDetails/:param', {
title: 'Error Details',
templateUrl: 'path/to/errorDetails.html'
});
Now you can send param using $location.path as follow:
$location.path("/errorDetails/"+param);
And you can access route parameter on resultant page's controller as follows:
$routeParams.param
I want to add controls to sort a table which is rendered in a partial view. The partial view is called using a signalR method. Every time the server updates the database with new information it calls the javascript method to return a new partial view to <div id="customersTable">.
I need a way to pass a query to the controller, and make the last query sent persistent so that when signalR calls the controller action again, the clients actions are remembered.
In addition to sorting I would also like to implement child rows that are expandable via a toggle button in an additional column. I'm not sure how feasible that is using partial views and signalR in this way.
I have partially solved this by adding JQuery controls to the main page. However when AJAX updates the DOM, the controls are reset to their default state, which is something I ultimately want to avoid happening.
Here is the partial view:
#model IEnumerable<XXXX.Models.CustomerModel>
<table class="table table-hover">
<tbody>
<tr>
<th class="col-sm-2">
Name
</th>
<th class="col-sm-2">
SO Number
</th>
<th class="col-sm-2">
Report Time
</th>
<th class="col-sm-2">
Report Date
</th>
<th align="center" class="col-sm-1">
System Status
</th>
</tr>
#foreach (var item in Model)
{
<tr onclick="location.href = '#(Url.Action("SystemDetails", "Monitoring", new { id = item.ID }))'" #(item.Errors == 0 ? String.Empty : "class=danger")>
<td class="col-sm-2">
#Html.DisplayFor(modelItem => item.Name)
</td>
<td class="col-sm-2">
#Html.DisplayFor(modelItem => item.SONumber)
</td>
<td class="col-sm-2">
#Html.DisplayFor(modelItem => item.ReportTime)
</td>
<td class="col-sm-2">
#Html.DisplayFor(modelItem => item.ReportDate)
</td>
<td align="center" class="col-sm-1">
#if (item.Errors == 0)
{
<i class="glyphicon glyphicon-ok"></i>
}
else if (item.Errors > 0)
{
<i class="glyphicon glyphicon-warning-sign"></i>
}
</td>
</tr>
}
</tbody>
</table>
Here is the javascript method client side:
function getAllCustomers()
{
var tbl = $('#customersTable');
$.ajax({
url: '/Monitoring/GetCustomers',
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
tbl.empty().append(result);
}).error(function () {
});
}
And the controller method where the db context is sorted:
public ActionResult GetCustomers()
{
return PartialView("~/Views/Monitoring/_CustomersList.cshtml", db.Customers.OrderBy(c => c.SONumber).ToList());
}
I have created an e-commerce website and am using a label to display the products from my sql database, the image it shows of these products are not hyperlinks, but this is what I need them to be, I think I have written the right code but I have a "parentControl" error, could someone help plz?
Below is also a link to show you visually what is being asked. REMEMBER the picture is just an image, but needs to be a hyperlink!
private void FillPage()
{
ArrayList teesList = new ArrayList();
if (!IsPostBack)
{
teesList = ConnectionClass.GetTeesBySize("%");
}
else
{
teesList = ConnectionClass.GetTeesBySize(DropDownList1.SelectedValue);
}
StringBuilder sb = new StringBuilder();
HyperLink link = new HyperLink();
link.NavigateUrl = "http://google.com";
parentControl.Controls.Add(link);
foreach (Tees tees in teesList)
{
sb.Append(string.Format(#"<table class='TeesTable'>
<tr>
<th rowspan='1' width='150px'><img runat='server' src='{6}' /</th>
<th width='50px'>Name: </th>
<td>{0}</td>
</tr>
<tr>
<th>Size:</th>
<td>{1}</td>
</tr>
<tr>
<th>Price:</th>
<td>{2}</td>
</tr>
</table>",
tees.name, tees.size, tees.price, tees.id, tees.id, tees.id, tees.image));
LblOutput.Text = sb.ToString();
(https://dl-web.dropbox.com/get/CompetitiveStreakTemplate/Pic.png?_subject_uid=9403629&w=AAD63dzqPQcNMNSU0OwbVBrGjNGFvtt7VWJ6DKwlu4UoPw).
You need to close your <img> tag properly and wrap it in a <a> to make it a hyperlink. Also use <td> instead of <th> for data rows and not headers.
Something a bit more like:
<td rowspan='1' width='150px'>
<a href='{0}.aspx'>
<img runat='server' src='{6}' />
</a>
</td>
You should probably also tidy up the rest of the code appended to your table, checking what is a header or data, and using a <tbody> tag inside the <table>
Edit: looking closer it seems as though you aren't creating the table properly in the first place, change this chunk of your code to do the loop properly:
parentControl.Controls.Add(link);
sb.Append("<table class='TeesTable'><tbody>");
foreach (Tees tees in teesList)
{
sb.Append(string.Format(#"
<tr>
<td rowspan='1' width='150px'>
<a href='{0}.aspx'>
<img runat='server' src='{6}' />
</a>
</td>
<td width='50px'>Name: </td>
<td>{0}</td>
</tr>
<tr>
<td>Size:</td>
<td colspan='2'>{1}</td>
</tr>
<tr>
<td>Price:</td>
<td colspan='2'>{2}</td>
</tr>",
tees.name, tees.size, tees.price, tees.id, tees.id, tees.id, tees.image));
}
sb.Append("</tbody></table>");
LblOutput.Text = sb.ToString();
I am using Knockout and have the ViewModel bound to my data object in my ASP.Net MVC 4 project quite nicely like so:
$(document).ready(function() {
properties = #Html.Raw(Json.Encode(Model));
selectedProperty = properties[0];
viewModel = { properties: ko.mapping.fromJS(#Html.Raw(Json.Encode(Model))), selectedProperty: ko.observable()};
viewModel.setItem = function(item) {
viewModel.selectedProperty(item);
}
ko.applyBindings(viewModel);
Now I want to refactor my JavaScript so that the logic is encapsulated inside a class:
RealEstate.Search = function (properties) {
this.properties = properties;
this.selectedProperty = this.properties[0];
this.viewModel = { properties: ko.mapping.fromJS(this.properties), selectedProperty: ko.observable()};
this.viewModel.setItem = function(item) {
viewModel.selectedProperty(item);
}
ko.applyBindings(this.viewModel);
}
And I am instantiating that object in my HTML page like so:
$(document).ready(function() {
search = new RealEstate.Search(#Html.Raw(Json.Encode(Model)));
}
Now, I am getting the following error:
Error: Unable to parse bindings.
Message: ReferenceError: 'properties' is undefined;
Bindings value: foreach: properties
Here is the snipped HTML for the table bound to the ViewModel:
<div id="divDataTable" data-bind="with: properties">
<table id="dataTable" class="tablesorter">
<thead>
<tr>
<th>Address
</th>
<th>
Suburb
</th>
<th>Price
</th>
<th>Beds
</th>
<th>Baths
</th>
<th>Days Listed
</th>
</tr>
</thead>
<tbody data-bind="foreach: properties">
<tr data-bind="click: $root.setItem">
<td>
<label data-bind="text: $data.Street"></label>
<input data-bind="attr: { value : $index(), id : $index(), name : $index() }" type="hidden" />
</td>
<td data-bind="text: $data.Suburb"></td>
<td data-bind="text: $data.PriceFormatted"></td>
<td data-bind="text: $data.NumOfBedrooms"></td>
<td data-bind="text: $data.NumOfBathrooms"></td>
<td data-bind="text: $data.DaysListed"></td>
</tr>
</tbody>
</table>
</div>
</section>
<div id="divProperty">
<aside class="float-right" data-bind="with: selectedProperty">
<table>
<tr>
<td>
<label data-bind="text: $data.Street"></label>
</td>
<td>
<label data-bind="text: $data.PriceFormatted"></label>
</td>
</tr>
<tr>
<td colspan="2">
<img src="#" /></td>
</tr>
<tr>
<td>Beds:
<label data-bind="text: $data.NumOfBedrooms"></label>
</td>
<td>On OZMite:
<label data-bind="text: $data.DaysListed"></label>
</td>
</tr>
<tr>
<td>Baths:
<label data-bind="text: $data.NumOfBathrooms"></label>
</td>
<td>Year built:</td>
</tr>
</table>
</aside>
I would appreciate it if someone could shed some light on what I am doing wrong.
With the data-bind="with: properties" you are already "in the context" of the properties property inside your div.
So when you write <tbody data-bind="foreach: properties"> KO tries to find the properties property inside your properties array.
What you need is to use to reference the current binding context with the $data.
So your foreach should look like this:
<tbody data-bind="foreach: $data">
...
</todby>
I have a view in 2 sections.
The top section I input fields and submit to save them.
In the second section I have an autocomplete textbox. I select an item in autocomplete, and when I click submit I want to add that item to a datatable.
So for the first part when I click submit I save the details via a HttpPost method on the controller.
For the second part I intend to save it via an Ajax call for the controller and then bring back a partial view with the results. I have not coded the partial view yet, that is next.
Now I am new to Ajax.BeginForm and I am struggling with it.
I was hoping that the submit button inside the Ajax.BeginForm would only apply to that part of the form.
But in fact it calls the HttpPost method for the whole form.
So how do I fix this?
My view looks like;
#using ITOF.HtmlHelpers
#model ITOF.Models.OngoingContractViewModel
#{
ViewBag.Title = "EditOngoingContractDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("EditOngoingContractDetails", "Contract", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Contract.ContractId)
<h1>Edit Ongoing Contract Details</h1>
<fieldset>
<legend>#Model.Contract.Heading</legend>
<p>Where you see <span class="error">*</span> you must enter data.</p>
<table>
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.EndDate)
</td>
<td>
#Html.EditorFor(model => model.Contract.EndDate)
</td>
</tr>
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.Organogramme)
</td>
<td>
<input type="file" id="PDF" name="file" />
#Html.HiddenFor(model => model.Contract.Organogramme)
</td>
</tr>
#if (!string.IsNullOrWhiteSpace(Model.Contract.Organogramme))
{
<tr>
<td></td>
<td>
The current organogramme is <span class="HighlightTextRed">#Model.GetOrganogrammeName()</span>
for the contract <span class="HighlightTextRed">#Model.Contract.ContractName</span><br/>
Click here to see the last saved organogramme
</td>
</tr>
}
<tr>
<td style="text-align: right">
#Html.LabelFor(model => model.Contract.AssistantRLOManagerId)
</td>
<td>
#Html.DropDownListFor(model => model.Contract.AssistantRLOManagerId, Model.AssistantRloManagerSelectList, "--N/A--")
</td>
</tr>
#if (this.TempData["SuccessMessage"] != null)
{
<tr>
<td colspan="2" class="success">#this.TempData["SuccessMessage"].ToString()</td>
</tr>
}
<tr>
<td colspan="2" style="padding-top: 20px; text-align: center;"><input type="submit" value="Save" /></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>Add an existing Site to this contract: </legend>
#using (Ajax.BeginForm("AddExistingSite", new AjaxOptions { UpdateTargetId = "siteRows" }))
{
<input type="text" name="q" style="width: 800px"
data-autocomplete="#Url.Action("SiteSearch", "DataService", new { contractId = #Model.Contract.ContractId })" />
<input type="submit" value="Add site to contract" />
}
#if (Model.SiteList.Count > 0)
{
<table id="siteDataTable" class="display">
<thead>
<tr>
<th>Main Site?</th>
<th>Type</th>
<th>Address</th>
<th>Map</th>
<th>Telephone</th>
<th>Email</th>
</tr>
</thead>
<tbody id="siteRows">
#foreach (var item in Model.SiteList)
{
<tr id="#item.SiteContract.SiteContractId">
<td>#item.SiteContract.MainSiteFlag</td>
<td>#item.Site.SiteType</td>
<td>#item.Site.Address</td>
<td>#item.Site.MapUrl</td>
<td>#item.Site.Telephone</td>
<td>#item.Site.Email</td>
</tr>
}
</tbody>
</table>
<div class="add_delete_toolbar" />
}
#Html.ListLink("Back to List")
</fieldset>
}
Oh no, you just cannot nest HTML forms. That's not supported. You will have to rethink your design. This really has absolutely nothing to do with ASP.NET MVC and things like Html.BeginForm or Ajax.BeginForm. The HTML specification simply tells you that the <form> tag cannot be nested and if you nest it you will get undefined behavior that could vary between browsers.
For example you could implement the autocomplete functionality using jquery UI autocomplete plugin and get rid of the Ajax.BeginForm.