I have a table with input inside it to allow users edit the quantity of goods, the total values of all goods in the bill is calculated when user input the quantity via ng-change. In ng-change, i will check if the quantity is large than current stock, i will reset it to old value and do not update total values (plus show msg err etc.....). Everthing gone fine, but my only problem is I can not make the input update with the model.
<table st-table="goodsOfBillList" st-safe-src="sellDetailList" class="table table-striped">
<tr ng-repeat="row in goodsOfBillList" st-select-row="row" st-select-mode="single" ng-show="!sellBillCtrl.isLoading">
<td>
<input id="quantity" ng-model="row.quantity" ng-model-options="{ updateOn: 'blur' }"
placeholder="current stock : {{row.currentStock}}"
class="form-control input-md" required="" type="number" min="1" max="{{row.currentStock}}"
ng-change="updateTotal(row, '{{row.quantity}}')">
</td>
</tr>
</table>
When i input an invalid value (50) like the picture below, quantity is reset back to previous value (5), but the input in the model doesn't update
$scope.updateTotal = function (row, oldVal)
{
//because I set max value, if I input an invalid value, row.quantity become undefined
//Checked by using alert()
if(typeof row.quantity === "undefined")
{
row.quantity = oldVal;
alert(JSON.stringify(row));
return;
}
//logic if valid value
};
i am using input in smart-table, and the table inside a boostrap modal
Related
I am fetching some data from the database server and displaying the same in tabular format on my GUI. I want to achieve the following in my GUI design
(a) Any cell in the table should be editable except the first column in the table.
(b) The first row of the table, if added newly to the GUI for accepting new inputs from the user, should be exempted from the above rule i.e., all columns of the first row should be editable.
To achieve this I wrote the following code.
HTML Code
<tbody>
<tr ng-repeat="x in sensordata">
<td>
<input class="form-control" type="text" ng-model="x.name" placeholder="Sensor name" ng-readonly="namereadonly" ng-init="ctrl2.setReadOnly(x.name,$index)"/>
</td>
<td>
<input class="form-control" type="text" ng-model="x.unit" placeholder="Measurement Unit" required/>
</td>
<td>
<input class="form-control" type="text" ng-model="x.type" placeholder="Sensor Type" required/>
</td>
<td>
<input class="form-control" type="text" ng-model="x.periodicity" placeholder="Periodicity" required/>
</td>
<td>
<input class="form-control" type="text" ng-model="x.formula" placeholder="Formula" required/>
</td>
<td>
<input class="form-control" type="email" ng-model="x.vendor" placeholder="Email Id" required/>
</td>
</tr>
</tbody>
Controller code is as follows.
this.setReadOnly = function(name,idx) {
console.log('name ' + name + ' idx ' + idx);
if (name === undefined || name === null || name === '') $scope.namereadonly = false;
if (name !== '' || name !== undefined || name !== null) $scope.namereadonly = true;
};
When I am executing above code the first column of all the rows are getting uneditable as expected. But when I am adding new row to the (by adding new empty JSON object in the sensordata array in another function of the same controller) GUI, the first column of the row is getting uneditable which should not be the case as per the first if statement in the above method. I am unable to figure out why it is happening.
you can try if else statement, which sets the variable properly
this.setReadOnly = function(name,idx) {
console.log('name ' + name + ' idx ' + idx);
if (name === undefined || name === null || name === '') $scope.namereadonly = false;
else (name !== '' || name !== undefined || name !== null) $scope.namereadonly = true;
};
<input class="form-control" type="text" ng-model="x.name" placeholder="Sensor name" ng-model-options="{ updateOn: 'blur' }" ng-readonly="x.name.length"/> this line solved my problem. Without ng-model-options attribute as soon as one types a character in the newly added row the first column is becoming uneditable. With ng-model-options this issue is resolved as now the column would become uneditable upon moving focus from the input field.
No method is to be written in the controller.
you can put the condition directly in ng-readonly as below
<input class="form-control" type="text" ng-model="x.name" placeholder="Sensor name" ng-readonly="{{x.name !== '' && x.name !== undefined && x.name !== null}}" />
a) Any cell in the table should be editable except the first column in
the table. (b) The first row of the table, if added newly to the GUI
for accepting new inputs from the user, should be exempted from
the above rule i.e., all columns of the first row should be editable.
There are plenty solutions but it depends on you/your needs. Here I would like to share you 2 logics :
adding new key for the new object entered by user and use this new key to distinct them with old object ng-readonly="x.new" and new object should have this key: {name:"", new: true}
Store the length of main array, and use this to distinct the new object entered ng-readonly="$index < mainlength" and mainlength is something like: $scope.mainlength = angular.copy($scope.sensordata.length) (use of angular.copy ) see http://plnkr.co/edit/zCcyPTG3EybL4IjsOpz4?p=preview
I have created a list of ng-repeat products rows.
Each row contains a search field that contains the typeahead
When successful, which it always is, goes on to fill the rest of the forms
My problem begins when I try to save this form, nomatter what I do, the values are just never captured. What can I do to achieve this?
<tr ng-repeat="item in vm.invoiceProducts" >
<td>
<input type="text" ng-model="item"
uib-typeahead="item as item.name for item in
vm.searchinvoiceProducts($viewValue)">
<textarea ng-model="item.description"
ng-model-options="{ getterSetter: true }" >
</textarea>
Example Code:
<table>
<tr>
<td>Class</td>
<td> Input one </td>
<td> Input two </td>
<td> Total </td>
</tr>
<tr ng-repeat= "x in records">
<td>My {{x.class}} </td>
<td><input type="tel" ng-value="x.tel" ng-model="telephone"></td>
<td><input type="tel" ng-value="x.inone" ng-model="inone"></td>
<td><input type="tel" ng-value="x.intwo" ng-model="intwo"></td>
<td><input type="tel" ng-value="x.total" ng-model="total"></td>
</tr>
<tr>
<td colspan="5" class="text-center"> <input type="button" value="Save" ng-click="mydata(records)"> </td>
</tr>
</table>
Initially ng repeat records contains only details part bydefault.
$scope.records = [
{
"class" : "Personal",
},
{
"class" : "Socail",
},
]
After submit, angular dynamically add those field which filled by user
Intially User will see only
1.Class part with 3 blank input field for inone, intwo and total and one blank telephone field.
What I want
1.There should be validation to telephone field of
A. Personal class which allow only 6 digits, and
B. for Social class it should allow 10 digits.
The range for entering value in Personal's inone field is 0-10 and intwo field is 11-30.
The range for entering value in Social's inone field is 30-40 and intwo field is 40-60.
4.Total field should calculate total of whatever entered in inone and intwo model of there respective class .Note that total field is generated from ng repeat so we cannot directly make total.
What about something along the line ...
<td ng-if="x.class=='Personnal'"><input type="tel" ng-maxlength="5" ng-model="x.inone" ng-change="x.total=x.inone+x.intwo"></td>
<td ng-if="x.class=='Social'"><input type="tel" ng-maxlength="5" ng-model="x.inone"></td>
<td ng-if="x.class=='Personnal'"><input type="tel" ng-minlength="11" ng-maxlength="15" ng-model="x.intwo" ng-change="x.total=x.inone+x.intwo"></td>
<td ng-if="x.class=='Social'"><input type="tel" ng-minlength="16" ng-maxlength="20" ng-model="intwo"></td>
Tu sum it up :
ng-value is useless, bind your data directly to x.[value]
use ng-if to switch between the different classes
use ng-minlength/ng-maxlength for the validation
use ng-change to recompute total everytime, you may want to add a readonly/disabled flag in the total field. If total is not a string concatenation, use a function that will be called in your controller for the proper conversion and sum it up.
Can any one help how to get input and selected values by dynamically added with angularjs?
Here is my code in Plunkr
When I select vegtables, another input shows with some values. when I click submit button I need a json like
{
"itemName":"Mango",
"itemType":"fruits"
},
{
"itemName":"Carrot",
"itemType":"vegtables",
"iteminfo":"you selected Carrot"
},
{
"itemName":"Apple",
"itemType":"fruits"
}
I forked your plunker
You can bind itemInfo to an item object using ng-model. Rather than placing the text in a value attribute I just initialized the model value using ng-init.
<tr ng-repeat="item in Items">
<td>
<input type="text" ng-model="item.itemName">
</td>
<td>
<select ng-model="item.itemType">
<option value="">--Select--</option>
<option vaue="fruits">Fruits</option>
<option value="vegtables">Vegtables</option>
</select>
</td>
<td>
<div ng-switch on="item.itemType">
<input type="text" ng-model="item.itemInfo" ng-switch-when="vegtables" ng-init="item.itemInfo='you selected '+ item.itemName">
</div>
</td>
</tr>
Also I had to change the Items array to match your requested naming:
$scope.Items = [{itemName: "Mango"}, {itemName: "Carrot"}, {itemName: "Apple"}];
You can parse the JSON object in a for loop to get the selected value and add the new key value pair.
angular.forEach($scope.vegetables, function(value, key){
if(value.itemName== 'Carrot')
value.iteminfo = 'you selected Carrot';
});
I guess you might be looking for something like this, if I am not wrong.
I have a table with different rows (react components). This rows are named service_users. When i click the save button of a row, a registerServiceUser method is called which updates the state in the parent component with a splice function. But after the state changes the input values from the saved row are passed to the next component (see screenshots).
The saved row is here the one with the name Milan den Vliet, after the save (which involves a state change) the value 23:00 and 1,00 are passed to the row of Finn de Dekker.
How can i prevent this behavior?
Service user child component code:
return (
<tr>
<td style={tdStyle}>{driverIcon}</td>
<td style={tdStyle}>{this.props.name}</td>
<td style={tdStyle}>{moment(this.props.startTime).zone('00:00').format('HH:mm')}</td>
<td><input type="text" onChange={this.handleEndTimeChange} className="form-control" /></td>
<td><input type="number" onChange={this.handlePauseChange} className="form-control" defaultValue={this.state.pause_time} /></td>
<td><input type="number" step="any" onChange={this.handleWorkHoursChange} className="form-control" value={this.state.work_hours} /></td>
<td><input type="number" step="any" onChange={this.handleExtraHoursChange} className="form-control" placeholder="Extra uren" style={extraHoursBackground} /></td>
<td style={tdStyle}>{driverField}</td>
<td style={tdStyle}>Opslaan</td>
</tr>
);
After save i update the state with this:
this.setState({ service_users: update(this.state.service_users, {$splice: [[index, 1]]}) });
I assume that you have a for-loop somewhere to generate the user rows. If this is the case, each row must have a unique key, preferably user ID or something similar. In that case
return (
<tr>...</tr>
)
must be changed to
return (
<tr key={this.props.id}>...</tr>
)
Unless you tell React to use a key, it just assumes that the top row is always the same, and just changes the values that have changed.
Update: Take a look at this fiddle. It doesn't do the same thing as your app, but the concepts of changing state and removing the proper elements should apply nevertheless: https://jsfiddle.net/jy0cgemz/