How to disable/enable sorting while editing in Angularjs - angularjs

I have a editTable like this:
<tr ng-repeat='guest in guestList | orderBy:orderByField:reverseSort'>
<td><span ng-show='!guest.isedit'>{{guest.firstname}}</span><span ng-show='guest.isedit'><input type="text" ng-model='guest.firstname'/></span></td>
<td><span ng-show='!guest.isedit'>mode_edit</i></span><span ng-show='guest.isedit'><button ng-click='contactUpdate(guest)'>OK</button></span></td>
</tr>
in my controller:
$scope.editGuest = function(guest){
delete $scope.orderByField;
guest.isedit = true;
};
$scope.contactUpdate = function(guest){
//Save the change then put the order back to re-order the table
$scope.orderByField = 'firstname';
}
As you can see, this is a editable table, if I click edit, the table becomes editable. I want to disable the sort when editing, until user finish editing and hit the OK button(Which already saved in the server), then I will re-order with new data. The problem is for the first time I fire editGuest(guest),it will still jump. Is there any way I can achieve this?

You need to have a different ng-model on your input box like this :
<tr ng-repeat='guest in guestList | orderBy:orderByField:reverseSort'>
<td>
<span ng-show='!guest.isedit'>{{guest.firstname}}</span>
<span ng-show='guest.isedit'><input type="text" value="{{ guest.firstname }}" ng-model='firstname'/></span>//I have set the value to the guest's firstname to default the name when the input box becomes active. You can also use ng-init to achieve it.
</td>
<td>
<span ng-show='!guest.isedit'>mode_edit</i></span>
<span ng-show='guest.isedit'><button ng-click='contactUpdate(firstname)'>OK</button></span></td>
</tr>
In your Controller :
$scope.contactUpdate(guest, name){
guest.firstname = name;
name = '';//EDIT
}

You need to remove binding first for this.
Create clone of guestList object and do the editing operation on it.
once it is done assign the clone object back to guestList.
e.g.
var dummyGuestList = angular.copy(guestList)
//some operation on dummyGuestList ;
guestList = dummyGuestList //assign bacl again

Related

Laravel: Generated buttons with loop (How to tell which one is click)

Hello Again Stockoverflow,
Hope all is well with you,
Can you help me again with Laravel/Ajax?
From the given code below I generated the table shown on the picture,
what I want to accomplish is to save each row when a button is click,
I know enough ajax to do the saving, the problem is how can I tell ajax and jquery which row button is click and which text input has the value since, the text inputs and buttons are generated with loop/array?
Thanks.
if($list_factors)
{
foreach ($list_factors as $key => $list_factor) {
// dd($list_factors);
$output.='<tr>'.
'<td>'.$list_factor->id.'</td>'.
'<td>'.$list_factor->factor_description.'</td>'.
'<td><input type="text" id="score" /></td>'.
'<td><button class="btn btn-info" id="submitScore">OK</button></td>'.
'</tr>';
}
return Response($output);
}
First of all, you can't use id="submitScore" attribute in the button generated within the loop because id must be unique. Instead you can use class="submitScore". Also, you can't use id="score" in the input, use class="score" Since you are going to use jQuery then you may try something like this:
// Register the event handler on 'submitScore' class of button
$('button.submitScore').on("click", function(e) {
var row = $(this).closest('tr');
var inputValue = row.find('.score').val();
console.log(inputValue);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td><input class='score' /></td>
<td><button class='submitScore'>OK</button></td>
</tr>
<tr>
<td><input class='score' /></td>
<td><button class='submitScore'>OK</button></td>
</tr>
</table>

How to add a new record and not update previous record in angularjs

How do I add a new record and have angular "forget" the new item added after I click the corresponding button.
The ability to add a record works and when I add the new record it display in the table I have, correctly, However my problem is that when I go to add a second record ie I remove the previous input and type something else. This results in the newly added record below to also change.
In short after I add an item to my array I want angular to forget it. How do I accomplish this.
In my controller I have this
(function () {
var app = angular.module("mainApp");
var ordersController = function ($scope,$filter, ordersService,customerService) {
$scope.orders = [];
$scope.addOrder = function (newOrder) {
$scope.orders.push(newOrder);
}
app.controller("ordersController", ["$scope","$filter", "ordersService","customerService", ordersController]);
}());
in my html I have this
<div><table>
<tr>
<td><input ng-model="item.quantity" type="text" /></td>
<td><button type="button" ng-click="addOrder(item)">Add Line Item</button></td>
</tr>
</table></div>
<div>
<table>
<tr ng-repeat="order in orders track by $index">
<td>
{{ order.quantity }}
</td>
</tr>
</table>
</div>
The problem might be that you are adding the newOrder object to the array while Angular keeps it's model bound to that object. Try using Angular's copy functionality like this (assuming that you are using Angular 1):
$scope.addOrder = function (newOrder) {
var copiedOrder = angular.copy(newOrder);
$scope.orders.push(copiedOrder);
}
The documentation for the copy method can be found here.

Prevent angular from sorting list item alphabetically in real time

I am trying to fix a bug with an angularjs list.
When an item in the list is edited, the record is sorted alphetically in real time and it jumps to a new position in the list.
This is proving problematic as when someone tries to edit a record, "ABC" for example, if they put a "Z" in front of it it jumps to the last page on the list.
The text input value is bound directly to the model, which I suspect is the issue, as the data-ng-repeat directive ensures that the data is sorted alphabetically.
As such I tried changing the data-ng-model binding to data-ng-bind, as it is my understanding that if the input value is changed, ng-model updates the model while ng-bind doesn't.
I would greatly appreciate any advice.
HTML:
<form name="companies" class="clearfix" novalidate data-ng- hide="loadingIcon">
<table>
<tbody>
<tr data-ng-repeat="company in data | orderBy: 'NAME' | siftPage: startIndex: endIndex">
<td width="60%">
<span data-ng-hide="edit"> {{ company.NAME }} </span>
<div class="form-field col-sm-9" data-ng-show="edit">
<input type="text" data-ng-bind="company.NAME" />
</div>
</td>
<td>
<a class="icon edit" data-ng-click="edit = !edit; changed = edit ? edited(company) : changed(company);" href="#"></a>
</td>
<td>
<a class="icon delete" data-ng-click="removeCompany(company)" href="#"></a>
</td>
</tr>
</tbody>
</table>
I'm new to angular so please forgive me if I haven't included enough information. I will update update with any further information as requested.
I believe it is the ng-repeat with the orderBy: 'Name' clause that is the actual issue. It will make sure that the order is maintained even after an edit.
If you want to order initially before edits, copy the name as initialName onto each of your json objects and set the orderBy to 'initialName'. Since you wont be updating the initialName on an edit it wont update via the order by.
If you create the copy as a function to create the initialNames, you could call it through a button to re-sort the data.

Weird bug: AngularJS can search single fields but not multiple fields

I am writing an app using Angular 1.3. I want to search through a table by any word/field; one search box for everything.
Currently I am able to get my search box to search through a specific field fine by doing:
<label>Search: <input ng-model="searchKeyword.title"></label>
or
<label>Search: <input ng-model="searchKeyword.author"></label>
Those work fine. However, when I try to search all the fields at the same time by doing:
<label>Search: <input type = "text" ng-model="searchKeyword"></label>
It doesn't work at all.
This is my code on the table:
<label>Search: <input ng-model="searchKeyword"></label>
<table ng-repeat="post in posts | orderBy: sort | filter: searchKeyword">
<tr>
<td> {{post.title}} </td>
<td> {{post.author}} </td>
<td> {{post.content}} </td>
<td> {{post.date | date: "d/M/yyyy"}} </td>
</tr>
</table>
And this is inside my main controller:
$scope.posts = posts.posts;
$scope.searchKeyword = "";
Please tell me what exactly is causing this weird bug. Thank you.
Its because ng-repeat create a new scope and cannot write in to a primitive property of its parent scope.but can write in to an object of its parent scope.
A scope (prototypically) inherits properties from its parent scope.
this post explains it well.What you want here is a custom filter check the ng-modal against each property in your object.
. filter('customFilter', function() {
return function(product,query) {
var out = [];
angular.forEach(product,function(value,key){
if(value['author'].indexOf(query)>-1 || value['title'].indexOf(query)>-1)
{
out.push(value)
}
})
return out;
}
})
Here is a working example
i found this post very late. Anyway my suggestion may helpful to other viewer.
There is a solution for weird bug in weird way.
I found this post is very useful for use of multiple filters in controller with example of big data table search.
(after reading the above linked post)
But you dont need to include multiple watcher and multiple input fields in every column of table, for your scenario you will just need the below code change after static json declaration.
$scope.$watch('searchKeyword', function(val) {
$scope.items = $filter('filter')($scope.items2, val); });
considering searchKeyword is the ng-model of input field to search.

Make a single button active in a group of buttons created by a ng-repeat

I am working on a directive that displays a table using ng-repeat directives. Each cell in the table may contain a button depending on the data. Here is the pertinent snippet of the template.
<tbody>
<tr ng-repeat="row in data.rows">
<td>{{ row.rowName }}</td>
<td ng-repeat="cell in row.cells">
<button id="button-{{ row.id }}-{{ cell.id }}"
class="btn btn-primary"
ng-show="cell.isActive"
ng-click="onClick(row.id, cell.id, $event)">Select</button>
</td>
</tr>
</tbody>
In the controller I have
$scope.onClick = function (rowId, cellId, event) {
$scope.selectedRowId = rowId;
$scope.selectedCellId = cellId;
$scope.selectedButtonId = event.target.id;
};
The goal is to make it such that when a user clicks a button in the table, that button becomes active. When the user clicks on another button, it will become active making the previously active button inactive. This functionality will be used to drive what is displayed on another section of the page.
I have tried a few things, but I think the most angular way of doing things is to use ng-class in the buttons to apply the active and inactive classes based on what button has been clicked. To this end, I am assigning them all unique ids and tracking which button has been clicked based on the event.
The problem is I can not figure out how to make the ng-class work. Is there some way I can get the id of the current button that I am in, or am I going about this completely wrong in the first place.
Thanks.
In your button code set the html ng-class attribute :
ng-class="active : selectedRowId = row.id & selectedCellId = cell.id"

Resources