AngularJS directive append a tablerow from one table to another table - angularjs

I'm working with AngularJS at the moment and in my current Project i've got to append a row from table1(in which a button is clicked by a user) to a 2nd table. On top of this the button also has to perform a $http.post(...).
So what i got is a table with data populated by ng-repeat and in one of the td's i have a button with the ng-click directive which executes a function with a $http.post.
html:
<table id="tableOne">
<thead>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th></th>
</thead>
<tbody id="source">
<tr ng-cloak ng-repeat="person in persons">
<td>{{ person.id }}</td>
<td>{{ person.name }}</td>
<td>{{ person.age }}</td>
<td><button ng-click="movePerson(person.id)">Move to 2nd Table</button></td>
</tr>
</tbody>
</table>
When I click on the Button the function "movePerson(person.id) in my Controller will be called and that works fine.
controller:
$scope.movePerson = function ( id ) {
DataService.movePerson( id, { result: function ( data, status ) {
if( data.success === true )
{
$log.log( "person has been moved" );
}
}, fault: function ( data, status ) {
$log.log( "an error has occured" );
} } );
};
'DataService' is handling my $http requests.
Now I want to move the tablerow where the button was clicked to another table(id="tableTwo") with tbody id="target".
I've read you shouldn't use jQuery in your Controller.. so is there an "angular-way" to do this? Because i would like to not include jQuery at all in my Project.
I thought you would use a directive for these kind of things, so that you can just add the directive in the button tag like the "ng-click" like this:
<td><button ng-click="movePerson(person.id)" move-tbl-row>Move to 2nd Table</button></td>
But since i'm new to Angular i don't know how my directive would look like. And will the "ng-click" still be executed then?
Geetings and Thanks.

You are asking how to move the row ....thinking like jQuery....when in fact you want to change the array the data object is in.
Here's a slight modification for you.
<!-- pass whole object into scope function -->
<button ng-click="movePerson(person)">Move to 2nd Table</button>
$scope.movePerson = function ( person ) {
var id= person.id;
/* on ajax success, remove from persons array */
var idx= $scope.persons.indexOf(person);
$scope.persons.splice(idx,1);
/* add person object to another scope array*/
$scope.another_array.push(person);
})

Related

Hide table rows in angular Js

I have a table, I am already given it CSS using ng-class if they satisfy a condition. Now I want to show only those rows who satisfy the same condition on a button click. I have wrote a controller which checks if the data received is within 24 hours are not and marks the data cell. Until this it's working.Now I need to add a button and show only the row which has this td marked as not received in time.
<tbody>
<tr ng-repeat ="data in log">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td ng-class ="{'data-notreceived' : dataNotReceived('data.receivedTime')}">{{data.receivedTime
}}
</tbody>
</table>
I think something like this should work. Basically, clicking the button will toggle between showing all or only the items marked as 'data not received'.
<tbody>
<tr ng-repeat ="data in log" ng-show="showAll || dataNotReceived(data.receivedTime)">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td ng-class ="{'data-notreceived' : dataNotReceived('data.receivedTime')}">{{data.receivedTime}}
</tr>
</tbody>
// in controller
$scope.showAll = true;
$scope.onButtonClick = function() {
$scope.showAll = !$scope.showAll;
return false;
}
From the information provided in question what I can say is: Use ng-show to show rows based on your condition.
<tr ng-show ="your_condition">
You could also use an ng-if rather than ng-show. See the differences here.
Really depends on how often the hide/show toggle needs to happen.
<tbody>
<tr ng-repeat="data in log" ng-if="showLast24Hrs(data.ReceivedTime)">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td>{{data.ReceivedTime}}</td>
</tbody>
and then in the controller,
$scope.showLast24Hrs = function(receivedTime){
if($scope.isLast24Hours) {
return receivedTime < 200; // Write your less than 24 hours check here
}
return true;
}
I wrote this demo on Codepen. Hope that helps.

ng-show tr element inside ng-repeat

I'm still pretty new to angular and am having trouble laying out the logic for my problem
Basically, I am using ng-repeat to generate a table filled with rows, and upon clicking any given row, to have a hidden row appear beneath the clicked on, so that I can load it up with data
My code looks as follows
<table class="table table-hover">
<tbody ng-repeat="order in resp.Orders" >
<tr ng-click='selectOrder(order);'>
<td>{{order.OrderId}}</td>
<td>{{order.Client}}</td>
</tr>
<tr ng-show('order.IsSelectedOrder')>
<td>Selected Order</td>
</tr>
</tbody>
</table>
As the code stands, the list generates with both rows visible at all times. At this point, that is the main problem
My selectOrder function looks as follows
$scope.selectOrder = function (order) {
order.IsCurrentOrder = true;
}
The syntax is incorrect and I think the property you set in the selectOrder function is incorect. It should be:
<tr ng-show="order.IsSelectedOrder">
$scope.selectOrder = function (order) {
order.IsSelectedOrder = true;
}
Docs for ng-show

Smart Tables Pagination Wont Work With Server Side Filtering

I have a smart table that I am working on in AngularJS. The table uses a custom pipe in order to search and sort its data. I also require that the table has working pagination, along with a drop down box so you can select the number of rows to be displayed (think datatables).
For searching and sorting, the custom pipe fires off my ajax requests without a problem. However, when I click on any of the page numbers or change the number of rows to show, the pipe is NOT fired.
The page numbers seem to be set to call setPage(page) (this is set by the st-pagination directive) but nothing happens - and no errors are thrown.
How do I get the custom pipe to fire upon changes to the number of rows displayed or when a page # is clicked in the pagination controls?
Here is my HTML:
<table class="table table-striped table-bordered" st-table="leadsCollection" st-safe-src="leads" st-pipe="serverFilter">
...
<tbody>
<tr data-toggle="modal" data-target="#modal-source" ng-repeat="source in leadsCollection" ng-click="rowClick($index);">
<td>{{source.leaddate}}</td>
<td>{{(source.distance > 100) ? 'Long Distance' : 'Local'}}</td>
<td>{{source.origin_city}}, {{source.origin_state}}</td>
<td>{{source.destination_city}}, {{source.destination_state}}</td>
<td>{{source.est_move_date}}</td>
<td>{{source.distance}} mi</td>
<td>{{source.number_bedrooms}} br</td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="8">
<div class="form-group col-md-1">
<label>Show:</label> <select class="form-control" ng-model="itemsByPage"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select>
</div>
<div class="pull-right" st-pagination="" st-items-by-page="itemsByPage"></div>
</td>
</tr>
</tfoot>
</table>
And here is the controller:
.controller('Leads', function ($scope, $http) {
$scope.leads = [];
$scope.leadsCollection = [].concat($scope.leads);
$scope.itemsByPage = "10";
$scope.rowClick = function (idx)
{
$scope.editor = $scope.leads[idx];
}
$scope.serverFilter = function(tablestate)
{
$http.post("/portal/api/loadleads",tablestate).success(function(response){
console.log(response);
$scope.leads = response;
$scope.leadsCollection = [].concat($scope.leads);
});
}
})
In order to get smart tables to fire the filters off, you have to set the numberofpages on data load. To get the above filter to work simply add:
tablestate.pagination.numberOfPages = response.totalPages;
Smart Tables seems to require this to be set in order for it to properly bind the events.

displaying selected list of values from one list into another onclick in angularjs

i have list of data displayed in table. As i click any td i display the list of selected values in another table.The Problem is if i select more than one row then in addition to the previous record next selected value should also be displayed but as per my code that do not happen.Should i use checklist? Or changes can be done in the existing one.code is as follows:
<table class="table table-hover" style="width:300px;">
<tr ng-repeat="work in jointworkdata">
<td ng-click="selectedVal(tab,work.jointwork_name)">{{work.jointwork_name}}</td>
</tr>
and display table is:
<table class="table table-hover"><tr>
<td >{{selectedData}}</td></tr>
code in controller is:
$scope.selectedVal = function(tab,val) {
if(tab==1)
{
$scope.selectedData=val;}
};
The output gives one record at a time and not all selected since fucntion is getting called on click.
You can accomplish this with 2 way binding https://docs.angularjs.org/guide/databinding .
Lets say you have a simple Controller that has the primary data to display and then a variable that collected the ones the user is adding on.
app.controller = function($scope) {
$scope.data = [1,2,3,4];
$scope.data2 = new Array();
$scope.add = function(item) {
$scope.data2.push(item);
};
};
Now in the view its simple as displaying both of them
<tr ng-repeat="item in data">
<td ng-click="add(item)">{{ item }}</td>
</tr>
...
<tr ng-repeat="item2 in data2">
<td>{{ item2 }}</td>
</tr>
Two way binding will take care of automatically rerunning that ng-repeat if any new items are added to the data2 array.

turn off re-sorting in angularJS while editing

I have an AngularJS app that lists a bunch of items in a table. Like this:
<table class='unstyled tmain'>
<tr>
<td ng-click='setSort($event)'>X</td>
<td ng-click='setSort($event)'>Desc</td>
<td ng-click='setSort($event)'>created</td>
<td> </td>
</tr>
<tr ng-repeat="item in items | orderBy:itemNormalizationFunction:sortReverse">
<td><input type='checkbox' ng-model='item.done'
ng-click='onCheckedChanged(item)'/></td>
<td><div edit-in-place="item.text"
on-save="updateItemText(value,previousValue,item)"></div></td>
<td><span class='foo'>{{item.created | dateFormatter}}</span></td>
</tr>
</table>
The table headers are clickable to set the sort order. The cell in the 2nd column in each data row is editable "in place" - if you click on the text it gets replaced with an input textbox, and the user can edit the text. I have a little directive enabling that. This all works.
The problem comes in while editing. Suppose I have it set to sort by "description" (the 2nd column). Then if I edit the description (via the edit-in-place directive), as I am typing in the input box, the sort order changes. If I change the first few characters, then angular re-sorts and the item is no longer under my cursor. Nor is it even focused. I have to go hunting through the list to find out where it got re-sorted to, then I can re-focus, and resume typing.
This is kinda lame.
What I'd like to do is tell angular to (a) stop re-sorting while I am keying in the input box, or (b) sort on a separate (not-displayed) index value that preserves the ordering before the edit began. But I don't know how to do either of those. Can anyone give me a hint?
I know this is sort of complicated so I'll try to put together a plunkr to show what's happening.
This is the plunkr that shows how I solved the problem.
http://embed.plnkr.co/eBbjOqNly2QFKkmz9EIh/preview
You can create custom filter and call that only when necessary. Example when you click on 'Grid header' for sorting or after dynamically adding/removing values to array, or simply click of a button(Refresh Grid)
You need to dependency Inject Angular filter and sort filter
angular
.module('MyModule')
.controller('MyController', ['filterFilter', '$filter', MyContFunc])
function ExpenseSubmitter(funcAngularFilter, funcAngularFilterOrderBy) {
oCont = this;
oCont.ArrayOfData = [{
name: 'RackBar',
age: 24
}, {
name: 'BamaO',
age: 48
}];
oCont.sortOnColumn = 'age';
oCont.orderBy = false;
var SearchObj = {
name: 'Bama'
};
oCont.RefreshGrid = function() {
oCont.ArrayOfData = funcAngularFilter(oCont.ArrayOfData, SearchObj);
oCont.ArrayOfData = funcAngularFilterOrderBy('orderBy')(oCont.ArrayOfData, oCont.sortOnColumn, oCont.orderBy);
}
}
and call in HTML something like:
<table>
<thead>
<tr>
<th ng-click="oCont.sortOnColumn = 'age'; oCont.RefreshGrid()">Age</th>
<th ng-click="oCont.sortOnColumn = 'name'; oCont.RefreshGrid()">Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="val in oCont.ArrayOfData">
<td>{{val.age}}</td>
<td>{{val.name}}</td>
</tr>
</tbody>
</table>

Resources