I was created table data and edit button and i am getting problem when i was trying to add edit data to specific row.
Here my plunkr :- http://plnkr.co/edit/QKz7nu458i8Il4OLmAyw?p=preview
Here HTML page
<table class="table table-bordered">
<thead>
<tr>
<th><input type='checkbox' ng-modal='isall' ng-click='selectallrows()'></th>
<th>ID</th>
<th>Name</th>
<th>EDIT</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='p in person' ng-class="{'success':tableselection[$index]}">
<td><input type='checkbox' ng-model='tableselection[$index]'></td>
<td>{{p.id}}</td>
<td>{{p.name}}</td>
<td><button class='btn btn-primary' ng-click='edit(p.id)'><span class="glyphicon glyphicon-pencil"></span>Edit</button></td>
</tr>
</tbody>
</table>
<div ng-show='editabledata'>
<form role='form' class='form-horizontal'>
<div class='form-group'>
<label>Id :-</label>
<input type='text' ng-model='pid' class='from-group col-sm-2'></div>
<div class='form-group'>
<label>Name:-</label>
<input type='text' ng-model='pname' class='from-group col-sm-2'>
</div>
<button class='btn btn-primary' ng-click='saveeditdata(pid)'>Save</button>
<button clas='btn btn-primary' ng-click='canceleditdata()'>Cancel</button>
</form>
</div>
Here my .js
$scope.person=[
{id:1,name:'devendher'},
{id:2,name:'Macha'},
{id:3,name:'Macha devendher'}
];
$scope.editabledata=false;
$scope.edit=function(id){
$scope.editabledata=true;
for(i=0;i<$scope.person.length;i++){
if($scope.person[i].id==id)
{
$scope.pid=$scope.person[i].id;
$scope.pname=$scope.person[i].name;
}
}
}
$scope.saveeditdata=function(id){
for(i=0;i<$scope.person.length;i++){
if($scope.person[i].id==id){
$scope.person[i].push({'id':$scope.pid,'name':$scope.pname})
}
}
}
i got error " $scope.person[i].push " is not a function
Is there any alternate way to add data to specific index of array?
I think you mean:
$scope.person.push({...})
Or
$scope.person[i] = {...}
This is very over complicated and you aren't taking advantage of using a single object for the form data. In addition you are using different property names for the editing vs original object. All the loops you are doing are unnecessary
Much simpler steps:
To edit object, pass whole object to controller function :
<button ng-click='edit(p)'>
In controller make copy of object and store reference to the selected one to update later
$scope.edit=function(person){
$scope.editabledata = true;
$scope.selectedItem = person;
$scope.editItem = angular.copy(person);
}
In edit form use full object reference in ng-model. No need to create individual variables, use the properties that already exist
ID : <input ng-model="editItem.id">
Name: <input ng-model="editItem.name">
In the save function extend the original object with the updated one
$scope.saveeditdata=function(){
// merge updates
angular.extend($scope.selectedItem , $scope.editItem);
// reset
$scope.editabledata = false;
$scope.editItem = {};
}
For delete see : How do I delete an item or object from an array using ng-click?
DEMO
Related
A table is to be created from taking values from json file where data should be displayed as radio buttons in columns(one value to be selected from each column). The selected values from each column should be displayed below the table. Could anyone please help me with this?
My Json is
"employees":[
{"firstName":"John", "lastName":"Doe" , "manager":"paul", "domain":"digital"},
{"firstName":"Anna", "lastName":"Smith", "manager":"Abraham","domain":"mechanics"},
{"firstName":"Peter", "lastName":"Jones", "manager":"Jonathan","domain":"physics"}
{"firstName":"Anna", "lastName":"carter", "manager":"Bravo","domain":"chemistry"}
{"firstName":"Watson", "lastName":"Daniel", "manager":"Pollock","domain":"biology"}
{"firstName":"James", "lastName":"Smith", "manager":"Tait","domain":"analogy"}
{"firstName":"Angel", "lastName":"Queen", "manager":"Mcgrath","domain":"mathematics"}
{"firstName":"Sana", "lastName":"Elizebeth", "manager":"Waugh", "domain":"english"}
]
Please note that you have to apply the returned value from inside the Observable. What you try is this in the end:
const employeesJSON = Observable<any>;
And then Angular tries to access the contained objects, which is not possible as an Observable<any> is not the same as an array of plain objects.
Try this solution instead:
protected employees: Array<Object>;
ngOnInit() {
this.http.get("api.myjson.com/bins/tshu8").pipe(map(res => {
if (res) {
this.employees = res.json();
}
}));
}
So here is my solution. Please note that this is only a suggestion:
We put 2 tables in the UI.
The first table is for input-purposes. Note the ngFor-loop in the tr of the table-body. Here you loop through your list of objects and with every new object a new tr gets created. Each tr contains 4 td's which contain input-elements of type "radio" and a span-element showing the content of the field. Controlled by the "name"-attribute each COLUMN builds a single unit. This means that a click on a radio button has only an effect on the state of every other radio button in the same column, not row! And each input-element's value gets set in order to provide it when the element is clicked.
The ngModel-attribute is the most important part of the story. Whenever you click a radio-button ngModel pushes the value of the clicked element into the connected variable. The second table then gets directly updated whenever ngModel updates one of the 4 variables (Interpolation). That's why a click on one radio button then prompts its value in the corresponding field of the "Output Table".
Hope this helps.
In your HTML-File:
<h1>Input Table</h1>
<div class="row" id="inputTableSector">
<table id="inputTable" class="table table-striped">
<thead>
<tr>
<td>first name</td>
<td>last name</td>
<td>manager</td>
<td>domain</td>
</tr>
</thead>
<tbody>
<tr *ngFor="let employee of employees;">
<td><input type="radio" name="firstName" [value]="employee.firstName" [(ngModel)]="currentFirstName"><span>{{employee?.firstName}}</span></td>
<td><input type="radio" name="lastName" [value]="employee.lastName" [(ngModel)]="currentLastName"><span>{{employee?.lastName}}</span></td>
<td><input type="radio" name="manager" [value]="employee.manager" [(ngModel)]="currentManager"><span>{{employee?.manager}}</span></td>
<td><input type="radio" name="domain" [value]="employee.domain" [(ngModel)]="currentDomain"><span>{{employee?.domain}}</span></td>
</tr>
</tbody>
</table>
</div>
<hr>
<h1>Output Table</h1>
<div class="row" id="outputTableSector">
<table id="outputTable" class="table table-striped">
<thead>
<tr>
<td>first name</td>
<td>last name</td>
<td>manager</td>
<td>domain</td>
</tr>
</thead>
<tbody>
<tr>
<td>{{currentFirstName}}</td>
<td>{{currentLastName}}</td>
<td>{{currentManager}}</td>
<td>{{currentDomain}}</td>
</tr>
</tbody>
</table>
</div>
In your TypeScript-File:
protected employees: Array<Object>;
protected currentLastName: string;
protected currentFirstName: string;
protected currentManager: string;
protected currentDomain: string;
ngOnInit(): void {
const employeesJSON = '[' +
'{"firstName":"John","lastName":"Doe","manager":"paul","domain":"digital"},' +
'{"firstName":"Anna","lastName":"Smith","manager":"Abraham","domain":"mechanics"},' +
'{"firstName":"Peter","lastName":"Jones","manager":"Jonathan","domain":"physics"},' +
'{"firstName":"Anna","lastName":"carter","manager":"Bravo","domain":"chemistry"},' +
'{"firstName":"Watson","lastName":"Daniel","manager":"Pollock","domain":"biology"},' +
'{"firstName":"James","lastName":"Smith","manager":"Tait","domain":"analogy"},' +
'{"firstName":"Angel","lastName":"Queen","manager":"Mcgrath","domain":"mathematics"},' +
'{"firstName":"Sana","lastName":"Elizebeth","manager":"Waugh","domain":"english"}' +
']';
this.employees = JSON.parse(employeesJSON);
}
I have a table showing me two parameters. What I would like to do is change the value of each of these parameters when a button is clicked. So each parameter has its own button with its own specific Ids (made with jinja2). for the value to be changed, I have to take the name of the parameter as an argument in a function, please look at the below picture:
my actual setup
So I have my input box and my button to be clicked:
<td> <input type=number size=5 id="{{key}}"> </td>
<td> <button onClick="change('{{key}}')" name="{{key}}">change value</button> </td>
the hard part is that, the change has to be made by executing a python script, so my function is described as :
function change(key){
$.getJSON($SCRIPT_ROOT + '/_change_value', {
a: $('input[name="key"]').val(),
b: $('button[name="key"]').val()}, function(data) { alert("Value was changed to " + data.result);});
}
For testing purpose I just made a python function that will return a only, to check if all went good, but unfortunately.
#app.route('/_change_value')
def change_value():
a = request.args.get('a', 0, type=int)
b = request.args.get('b', 0, type=int)
return jsonify(result=a)
a is returned as 0 always... I'm glad if someone can help me with this
I'm pretty sure the value key is not passed. Thanks a lot in advance
Edit: I made a mistake posting this question, id is present instead of name for the input, but still that did not resolve my problem...
Here you go with a solutio https://jsfiddle.net/1dvjqy11/
$('button').click(function(){
var a = $(this).closest('tr').find('input[type="number"]').val();
var b = $(this).closest('tr').find('td').first().html();
console.log(a, b);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Parameter</th>
<th>Value</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>GPS_Inject_to</td>
<td>127</td>
<td>
<input type="number" size=5 />
</td>
<td>
<button>
Change Value
</button>
</td>
</tr>
<tr>
<td>RPM2_SCALING</td>
<td>1</td>
<td>
<input type="number" size=5 />
</td>
<td>
<button>
Change Value
</button>
</td>
</tr>
</tbody>
</table>
I've used jQuery closest to get the parent tr and used jQuery find method to find the child elements.
Hope this will help you.
I'm populating a table from my database and it looks like this :
<form name = "Form" role="form" action ="php/teilnehmen.php" method="POST">
<fieldset>
<table width="100%" class="table table-striped table-bordered table-hover" id="dataTables-example">
<thead>
<tr>
<th>ID</th>
<th>Studienfach</th>
<th>Teilnehmer/in</th>
<th>Teilnehmen</th>
</tr>
</thead>
<tbody>
//<?php php code.....
$i =0;
$sizeofstudienfaecherseperate =
count($studienfaecherseperate);
for ($i; $i < $sizeofstudienfaecherseperate; $i++) {
?>
<tr class="odd gradeX">
<td ><?php echo($i+1);?></td>
<td class="studienfach"><?php echo($studienfaecherseperate[$i]);?>
<input type="hidden" name="PARAM_STUDIENFACH" id="PARAM_STUDIENFACH"
value="<?php echo($studienfaecherseperate[$i]);?>"> </input>
</td>
<td ><?php echo($teilnehmer[$i]);?></td>
<td width="10%">
<?php if ($teilnahmestatus[$i] =="0"){ ?>
<button type="submit" class="btn btn-success use-address"
name="teilnehmern"id="teilnehmen">Teilnehmen</button>
<?php }else{?>
<button type="submit" class="btn btn-danger use-address" name="teilnahme-beenden"
id="teilnahme-beenden">Teilnahme beenden</button>
<?php }?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</fieldset> <!-- /.table-responsive -->
the table is shown great, and my problem is when i try to submit my second column value "PARAM_STUDIENFACH" of a specific row to my php webservice. It always gives me back the last value. I know that because I'm using the same id in every row so it will be overwritten. I tried using JavaScript to return the value of the clicked row from other questions in the forum but it didn't work for me. I'm using a bootstrap table if that helps.
EDIT 1 :
Thanks to #Taplar answer I managed to find a solution to my problem. I used this JavaScript to retrieve the data and ajax to send a post request. This is the code I used :
$(".use-address").click(function() {
var item = $(this).closest("tr") // Finds the closest row <tr>
.find(".studienfach") // Gets a descendent with class="nr"
.text(); // Retrieves the text within <td>
$.ajax({
type: "POST",
dataType: "json",
url: "php/teilnehmen.php",
data: {PARAM_STUDIENFACH:item},
success: function(data){
alert(item);
},
error: function(e){
console.log(e.message);
}
});
});
my problem now is in the alert the "item" shows correctly but in my database it is saved as the following example :
item = a (shows in alert a)
item = a \n (it's saved like that in the database with spaces afeter \n)
i tried to trim the item before sending it but i got the same result
to get the item sent by ajax i'm using this line of code in :
$studienfach = null;
if(isset($_POST['PARAM_STUDIENFACH']))
$studienfach = $mysqli->real_escape_string($_POST['PARAM_STUDIENFACH']);
EDIT 2:
i managed to solve my second problem by doing this :
$pos= strpos($studienfach, "\\");
$studienfachtemp = substr($studienfach, 0,$pos);
trim($studienfachtemp);
if there is more elegent or correct way to do it ! please post it ! thank you all.
<elem1>
<elem2 class="getMe"></elem2>
<elem3></elem3>
</elem1>
Quick contextual lookup reference. Say you have a click event bound on all 'elem3' on your page. When you click it you want to get the associated 'elem2', not all of them. With the class you can contextually look this element up by doing...
//'this' being the elem3 that was clicked
$(this).closest('elem1').find('.getMe');
From the element you clicked, it will find the shared 'elem1' parent of both 'elem2' and 'elem3' and then find only the '.getMe' that belongs to that parent.
More reading material: http://learn.jquery.com/using-jquery-core/working-with-selections/
trying to figure out how to set up the radio button bindings in a table in knockout. I would like when the radio button on the table is selected. the entire selected record is available in the model. not quite sure how to set up the binding on the radio input. I assume I need to use $parent and a function for the value binding?
here is the fiddle. (the selected record does not do anything right now I would like it to be populated when the radio button is selected)
https://jsfiddle.net/othkss9s/5/
HTML
<table>
<thead>
<tr>
<th>Select</th>
<th>First</th>
<th>Last</th>
<th>Dept</th>
</tr>
</thead>
<tbody data-bind='foreach: employees'>
<tr>
<td><input type="radio" name="employees"></td>
<td data-bind='text: first'></td>
<td data-bind='text: last'></td>
<td data-bind='text: dept'></td>
</tr>
</tbody>
</table>
<div data-bind="with: selectedRow">
<h2>
Selected Record
</h2>
<p>
First: <span data-bind="first" ></span>
</p>
<p>
Last: <span data-bind="last" ></span>
</p>
<p>
Dept: <span data-bind="dept" ></span>
</p>
</div>
JS
function employee(first, last, dept) {
this.first = ko.observable(first);
this.last = ko.observable(last);
this.dept = ko.observable(dept);
}
function model() {
var self = this;
this.employees = ko.observableArray("");
this.selectedRow = ko.observable({});
};
var myViewModel = new model();
$(document).ready(function() {
ko.applyBindings(myViewModel);
myViewModel.employees.push(
new employee("Bob","Jones", "Hr")
);
myViewModel.employees.push(
new employee("Sarah","Smith", "It")
);
myViewModel.employees.push(
new employee("John","Miller", "It")
);
});
You have to perform two steps to get your code working.
First, apply bindings to radio buttons:
<input type="radio" data-bind="checked: $root.selectedRow, checkedValue: $data" />
checkedValue should contain actual value that corresponds the current radio button. In this case we refer $data variable that is whole employee object rather than simple (scalar) value.
checked binding should refer to an observable containing currently selected employee.
Second, correct the line where the selectedRow property is defined:
this.selectedRow = ko.observable();
Do not pass empty object as default value. Otherwise with binding won't work correctly.
By fixing the syntax of bindings in your second block that displays selected employee you will get something like this.
So I am trying to add additional columns to a table inside a form. Adding the columns themselves is not that difficult but I don't know how to go about setting their ng-models.
This is my current code:
(HTML)
<button ng-click="add()" type="button">+ column</button>
<table>
<thead id="inputtablehead">
<th class="theadlabel">(in 1.000 EUR)</th>
<th>{{startyear}}</th>
<th class="NBBCodesHeader">NBB Codes</th>
<th>Source</th>
</thead>
<tbody class="input">
<tr>
<td>number of months</td>
<td>
<input ng-model="input{{startyear}}.NumberMonths" type="text" class="{{startyear}}" required>
</td>
<td class="NBBCodes"></td>
</tr>
<tr>
<td>Fixed assets</td>
<td>
<input ng-model="input{{startyear}}.FixedAssets" class="{{startyear}}" type="text" required>
</td>
<td class="NBBCodes">20/28</td>
</tr>
<tr>
<td>Inventory</td>
<td>
<input ng-model="input{{startyear}}.Inventory" class="{{startyear}}" type="text" required>
</td>
<td class="NBBCodes">3</td>
</tr>
</table>
(JS)
angular.module("inputFields", []).controller("MyTable", function ($scope) {
$scope.startyear = new Date().getFullYear();
var nextyear = new Date().getFullYear() - 1;
$scope.add = function () {
$(".NBBCodesHeader").before("<th>"+nextyear+"</th>");
$(".input .NBBCodes").before('<td><input class='+nextyear+' type="text" required></td>');
nextyear--;
};
});
So in my JS the <input class='+nextyear+' type="text" required> should become something like <input ng-model="input'+nextyear+'.NumberMonths" class='+nextyear+' type="text" required> for the <td> element added next to the 'number of months' row.
I was thinking to give ea row an id in the form of NumberMonths and then look up the id when adding the column.
So my question would be: is this a valid way to do it and how would I get this id? Or am I overthinking it and is there an easier way to do this?
Use standard javascript [] object notation for variable property names.
<input ng-model="input[startyear].Inventory"
You shouldn't do DOM manipulations from a controller. It's not a good practice when working with AngularJS. A good rule to remember that is: don't use jQuery. It's a common mistake when starting working with AngularJS. And, in case you would be completely sure that you need to modify the DOM, do it always from a directive.
About your problem, maybe you can base your solution in create a data structure in your controller (a Javascript Object), and render it through a ng-repeat in your template. This way, if you modify the object (adding a new column), the template will be automatically updated.