I'm using ng-table in AngularJS with a Ruby on Rails backend. I'm using ng-table to display 10 rows at a time and I'm doing the search/sort and pagination on the server side.
The problem I'm having is the filter is sending a request to the server after every keystroke, is it possible to make ng-table wait until I want to send my filter to the server via a submit button?
$scope.tableParams = new ngTableParams({
page: if page then page else 1,
count: 10,
sorting: { invoice_no: 'desc'}
}, {
total: 0,
getData: ($defer, params) ->
Invoice.query params.url(), (data) ->
params.total($scope.total)
# put params in url
$location.search(params.url())
# Paginate / update table with new data
$defer.resolve(data)
})
My current view
<table ng-table="tableParams" show-filter="true" class="table">
<tr class='listing' ng-repeat="invoice in $data">
<td data-title="'Invoice No.'" sortable="'invoice_no'" filter="{'invoice_no':'text'}">
{{invoice.invoice_no}}
</td>
</tr>
</table>
An inline filter will get called many times.
To call the filter once when the submit button is clicked, add a click handler:
<button type="submit" ng-click="onSubmit()" />
In your controller, invoke your filter inside your click handler:
app.controller('ctrl', function($scope, $filter) {
$scope.$data = [];
$scope.onSubmit = function() {
$scope.$data = $filter('filter')($scope.data, {'invoice_no':'text'});
}
});
Related
I have an MVC 5 application that displays a list of 100+ unique URL's. The user can sort, search, and eventually click the URL from the list launching the website in a new window. I want to be able to track every time someone clicks a URL from that list. The URL list is populating as expected. View code below:
<table class="table table-condensed table-hover table-responsive table-striped">
<tr>
<th class="col-md-1">
#Html.ActionLink(" Name", "Index", new { sortOrder = ViewBag.ReportNameSortParam, SelectedReportCategory = ViewBag.SelectedReportCategory, FindReportName = ViewBag.FindReportName}, new { #class = "glyphicon glyphicon-sort", #title = "sort by name" })
</th>
</tr>
#foreach (var item in Model)
{
if (ViewBag.counter == "")
{
ViewBag.rowType = "normalRow";
ViewBag.counter = "1";
}
else {
ViewBag.rowType = "alternateRow";
ViewBag.counter = "";
}
<tr class=#ViewBag.rowType>
<td class="col-md-1" title="#Html.DisplayFor(modelItem => item.Report_Description) : #Html.DisplayFor(modelItem => item.SLA)">
#Html.DisplayFor(modelItem => item.Report_Name)
</td>
</tr>
}
</table>
What would be the best approach to track a user click when they are doing this via the View? I have a column in my table called 'Hits' that I would like to increment by 1 whenever that URL gets clicked. Ideally, after a user clicks a URL, I would like for the list to stay where it is and not have to refresh by hitting another controller and then repopulating. How can I write to the database on via the View?
as mentioned... capture the click event of each link clicked and perform an Ajax post to the relevant controller and action.
$(document).ready(function () {
$(document).on('click', 'a', function () {
var linkID = $(this).attr("id");
$.ajax({
type: "POST",
url: "#Url.Action("YourAction", "YourController")",
data:
{
linkid: linkID
}
});
});
});
hope that helps.
Consider standing up an action method that receives the URL and redirects to the final destination:
#Html.DisplayFor(modelItem => item.Report_Name)
In the controller, add:
public ActionResult Redirect(int id, string url)
{
//Get record using ID, and update Hits column
//Redirect to the final URL
return Redirect(url);
}
Be aware that if your URL's use any special characters, some encoding may occur... that might mean you have to do some encoding on the client end potentially. It's just good to test that out to confirm.
Im trying to pass some table data to its child vuestrap Modal component. The modal will be reused by all the Td's where the checkbox is calling the modal.
<div id="ordertbl" class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
...
</tr>
</thead>
<tbody>
<tr v-repeat="slides">
<td>#{ {NAME}}</td>
<td>#{ {MESSAGE}}</td>
<td> <input type="checkbox" v-on="click:showMod = true" v-model="published" > </td>
</tr>
</tbody>
</table>
<modal title="Modal" show="#{{#showMod}}" effect="fade" width="400">
<div class="modal-body">You will publish NAME, MESSAGE</div>
</modal>
</div>
when the checkbox is clicked. As you can see every row in the table has one checkbox so the data to be passed to the Modal will be unique to its row.
As Im new to Vue, besides Im trying to use Vuestrap to not reinvent things,
I dont know how to give that Data to the Modal when it pops.
new Vue({
el:'#ordertbl',
components: {
'modal':VueStrap.modal
},
data: {
showMod: false,
sortKey: '',
reverse:false,
slides: {
id: '',
name: '',
message: '',
published: ''
}
},
Basically I want to do the following
$('#exampleModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget) // Button that triggered the modal
var recipient = button.data('whatever') // Extract info from data-* attributes
// If necessary, you could initiate an AJAX request here (and then do the updating in a callback).
// Update the modal's content. We'll use jQuery here, but you could use a data binding library or other methods instead.
var modal = $(this)
modal.find('.modal-title').text('New message to ' + recipient)
modal.find('.modal-body input').val(recipient)
})
Pass the related data to the Modal, but with Vuestrap
You can use v-for="slide in slides". So every tr can get one of the slide object. Then you can pass it as a props to modal.
Extra ajax request is not required.
I manage to solve it with an ajax request depending on the Id clicked.
I'm trying to make a simple table with pagination by using Angularjs ng-table.
I included the js and css files to my rails 3 layout. When page first loaded, it displays a table then fires a http get to rails controller to get json(it works fine until this point).
What I'm trying to do is add pagination to my table.
I received error "angular is not defined" and there is no request from http get to rails controller. Please show me what I'm doing wrong here.
Thank you
(function(){
var app = angular.module("apTags", ["ngTable"])
// call back after table finished ng-repeat
.directive('onFinishRender', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
tableResponsiveAdjustHeight();
});
}
}
}
});
app.controller("apTagsController", [ "$http", function($scope, ngTableParams, $http){
// table has empty data when page first loaded
var apTags = this;
apTags.tags = [];
// Then it fires a http get to rails api to get data and append to table
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10 // count per page
}, {
total: data.length, // length of data
getData: function($defer, params) {
$http.get("ap_tags.json", {params: { api: true, page: params.page() } }).success(function(data){
apTags.tags = data;
$defer.resolve(data.slice((params.page() - 1) * params.count(), params.page() * params.count()));
});
}
});
}]);
})();
<div class="container" ng-app="apTags">
<div ng-controller="apTagsController as list">
<p><strong>Page:</strong> {{tableParams.page()}}</p>
<p><strong>Count per page:</strong> {{tableParams.count()}}</p>
<table ng-table="tableParams" id="table_tags" class="table table-condensed table-bordered table-hover">
<tr ng-repeat="tag in list.tags" on-finish-render="ngRepeatFinished">
<td data-title="'Tag'">{{tag.name}}</td>
<td data-title="'Share'">{{tag.share}}%</td>
<td data-title="'Direct Product Count'"></td>
</tr>
</table>
</div>
</div>
Im trying to do a preloader for a page
the index action controller:
myapp/FR/Index
public ActionResult Index(){
return View(db.SP_GetRegistrosFRByID(0).ToList());}
the view, there isnt a begin form because is a get request:
#foreach (var item in Model)
{
...etc...<tr>
<td>
#Html.DisplayFor(modelItem => item.CodIden)
</td>
<td>
#Html.DisplayFor(modelItem => item.Nombres)
</td> ...etc
As David says it's a broad and open-ended question and you can apply lot of approaches. You have not given details about how index gets called (form submit, button click ..)
First you need a div with the loader image in the view where you need the preloader to display.
<div id="loader" class="loader">
Working.. <img src="~/Images/loading_small.gif" />
</div>
and now the JS function that shows/hides the div with the loader image based on your data loading status.
function pageLoading(status) {
if (status == 'true') {
$("#loader").css('display', 'block');
}
else {
$("#loader").css('display', 'none');
}
}
Before making the AJAX request you can call pageLoading("true"); to start displaying the image and finally when the table data gets populated call pageLoading("false"); to hide the loading image. Something like
$.ajax({
url: 'your index method url',
success: function (partial) {
$('#results').html(partial);
pageLoading("false");
}
error: function () {
pageLoading("false");
}
});
I'm going to use a grid view. it contains a check box per row.
its for deleting row. for example when user checked some checkbooks and click on delete button checked rows have to delete.
Now How can I give checked rows ID's in my action ?
Do you have any ideas ?
Thanks.
OK. We assume that you want to retrieve a list of products and show them in a raw html grid.
First of all, arrange your view like this:
#model IEnumerable<MyPrj.Product>
// ... Other codes ...
<table id="tblGrid">
<tr>
<th>Delete</th>
<th>ProductName</th>
// ... Other Properties ...
</tr>
#foreach(var item in Model)
{
<tr id="tr#(item.ProductID)">
<td>
#Html.Raw("<input type='checkbox' id='chk#(item.ProductID)' onclick='chkChange(#chkID)' />");
</td>
<td>#item.ProductName</td>
// ... Other Properties ...
</tr>
}
</table>
<input type="button" id="btnDelete" value="Delete Selected Rows" onclick="performDelete()"/>
Now, you have your view and it will render the grid for you with the supplied model. Then, you need to add some javascript and jquery codes to perform the row deletion for you.
A function to handle checkbox clicks:
<script>
function chkChange(id) {
if ($(id).val() != 'false')
$(id).val('false');
else
$(id).val('true');
}
// ...
</script>
And finally, a function to handle delete button clicks:
function performDelete() {
var rows = $("input:checked");
rows.each(function () {
$(this).parent().parent().remove();
});
}
That's it! - you're done. The complete <script> blog is like the following:
<script>
function chkChange(id) {
if ($(id).val() != 'false')
$(id).val('false');
else
$(id).val('true');
}
function performDelete() {
var rows = $("input:checked");
rows.each(function () {
$(this).parent().parent().remove();
});
}
</script>
You could place the grid along with its checkboxes inside an HTML form and make the Delete button as submit button for this form. Then when the button is clicked, the form will be submitted and the values of the selected checkboxes will be sent to the controller action so that you could delete the corresponding records.