Here is my html snippet:
<tr ng-repeat="row in rowCollection">
<td><h6 id="{{$index}}">{{row.inventory_serialno}}</h6></td>
</tr>
<div class="form-group">
<label for="inventory_serialno">SL No:</label>
<input class="form-control" value="//I need the value of h6 here//" id="inventory_serialno" placeholder="Enter serial number">
</div>
Goal:
Get the value of an element inside ng-repeat (In this case the 'h6' tag value of each row)
Use that corresponding value to autofill the value of respective text box input present in each row.
The input text box is out of the ng-repeat scope.
For some reason i cant access the value of the h6 tag if i do this (gives a value null)
document.getElementById("1").innerHTML; //or even text()
Weirdly i noticed the above JavaScript code runs fine on the browser console but not on my script (which means its something to do with the angular element generation time.. May be i'm accessing it before it even got generated).
Nonetheless can someone please shed some light on the solution. Thanks in advance.
******** Updated with controller code *****
app.controller('InventoryCtrl', function ($scope) {
var x = document.getElementById("1").innerHTML; // giving a null value
console.log(x);
$scope.rowCollection = [{
id: 100,
inventory_serialno: 'HW13FGL'
}, {
id: 101,
inventory_serialno: 'SM123GH'
}, {
id: 102,
inventory_serialno: 'LK90100'
}];
});
You could do it like this:
<input value="{{rowCollection[2].inventory_serialno}}" />
Example
However I would place the input inside the ng-repeat to keep it clean, and achieve the layout you like inside a big wrapper, something like this:
<div class="grid" ng-repeat="row in rowCollection">
<div class="col">
<h6 id="{{$index}}">{{row.inventory_serialno}}</h6>
<hr>
<div class="form-group">
<form>
<input value="{{row.inventory_serialno}}"/>
</form>
</div>
</div>
</div>
If you need an input for each item, use ng-repeat.
Related
I am new to angular and I'm confused over this thing. I'm trying to populate a select box based on object inside an array. I want selectbox by using ng-repeat for that array... but initially i need to show only one selectbox after clicking add() next selectbox has to come. for ref:[initially one selectbox has to come]
HTML
<div class="col-lg-12" id="variant1" style="margin-top:10px" ng-repeat="variant in variants">
<div class="col-lg-4" style="text-align:right;padding-top:2px;padding-right: 20px" >
<label for="variant1name">Variant Name</label>
</div>
<div class="col-lg-6" >
<div >
<select class="form-control" ng-model="filterFormInputs.apps" ng-options="app.Application for app in variants" >
<option value="" disabled selected>Select an Application</option>
</select>
<label ng-repeat="checkbox in filterFormInputs.apps.details">
<input class="ecomtexttype1" type="checkbox" ng-model="checkbox.checked"> {{checkbox.name}}
</label>
</div>
</div>
</div>
Controller:
$scope.variants =
[
{"Application": "Color", "details":[{"name":"red"},{"name":"blue"},{"name":"black"}]},
{"Application": "Color", "details":[{"name":"red"},{"name":"blue"},{"name":"black"}]},
{"Application": "Color", "details":[{"name":"red"},{"name":"blue"},{"name":"black"}]}
]
I think that you can just have your add() function update the array... if things are configured correctly the new row should render due to the binding on the array.
As mentioned in comments you did not provide enough source code, so here is the assumed pseudo-code:
in html you might have
<button ng-click="$scope.add()">Add</button>
so in the controller
$scope.variants = [
// array of whatever you are displaying
{"foo":"bar1"},
{"foo":"bar2"}
];
$scope.add = function() {
variants.push({"foo":"bar_new"});
}
Have you considered using a Directive for this? That may work better, depending on your situation. Look into this: https://docs.angularjs.org/guide/directive
I need to execute an expression inside ng-model.
I have an array of integers which is shown in a list and input fields needs be generated on click of each item. All input fields should carry a generated value of ratio having base as 1. I also need to get the sum of numbers in the input field since the user can change the value.
My Code for this is
<div class="row" ng-repeat="kpi in SelectedKpiModel">
<div class="small-2 columns" ng-click="View.RemoveSelectedKPI($index)" style="margin-top:0.5em;border:ridge;padding-bottom: 1em; padding-top:0.5em; text-align:center"><span class="fa fa-scissors"></span></div>
<div class="small-4 columns" style="margin-top:0.5em;border:ridge;padding-bottom: 1em; padding-top:0.5em; text-align:center">
{{kpi.id}}
</div>
<div class="small-4 columns" style="float:left;margin-top:0.5em;border:ridge; padding:0em">
<input type="number" value="{{1/SelectedKpiModel.length}}" />
</div>
</div>
How do I get the count of all the field values if user changes or how do I store the value of each field and retrieve if need ?
I tried like ng-model="{{1/SelectedKpiModel.length}}" but it gave me error.
Thanks.
You can use something like this -
<input type="number" ng-model="getLength()" />
and your function -
$scope.getLength = () => {
return 1 / $scope.SelectedKpiModel;
}
I create a form dynamically in the view by iterating through an object that has the different questions to be asked to the user. One of the attributes of every question is formFieldName which is a a random string I use to give each form field a different name.
<form name="includedForm.newRequestForm" class="form-horizontal" role="form" novalidate>
<div ng-if="message.question.attributes.structure.type == 'object'">
<div ng-repeat="(index,objField) in message.question.attributes.structure.properties">
<div ng-if="objField.type == 'array'" class="form-group" show-errors>
<label for="{{objField.formFieldName}}" class="control-label col-sm-6">{{objField.title}}
<br /><i><small>{{objField.description}}</small></i></label>
<div class="col-sm-6">
<select class="form-control" name="{{objField.formFieldName}}" multiple ng-model="objField.userValue" ng-required="objField.required">
<option ng-repeat="option in objField.items.enum" value="{{option}}">{{option}}</option>
</select>
</div>
</div>
<div ng-if="objField.type == 'boolean'" class="form-group" show-errors>
<label for="{{objField.formFieldName}}" class="control-label col-sm-6">{{objField.title}}</label>
<div class="col-sm-6">
<input class="form-control" name="{{objField.formFieldName}}" ng-model="objField.userValue" type="checkbox" ng-value="option" ng-checked="message.question.attributes" />
</div>
</div>
</div>
</div>
<div class="col-sm-12">
<button ng-click="markAsDone(message)" class="btn btn-primary">Done</button>
</div>
<form>
In the controller I'm able to get the formFieldName attribute but I can't figure out how to use it to do the validation.
var MarkAsDone = function(message) {
$scope.includedForm = {};
var formField = message.question.attributes.formFieldName;
if ($scope.includedForm.newRequestForm.{{formField}}.$valid){
//submit the form
}
}
to answer you question:
first, {{}} is === $scope so you don't use that anywhere other than HTML. You use $scope in your JS and {{}} in HTML which creates a pipe (2-way binding) so that $scope.variable.property has bidirectional binding to {{variable.property }} in HTML.
$scope.includeForm.email === {{ includeForm.email }} === ng-model="includeForm.email" === ng-bind="includeForm.email"
if you set anyone of those all are set so if you set $scope it will show up in HTML and obviously as user input gets captured it is already in $scope ... all connected
when attempting to get the value from HTML back into JS you would need create and set a $scope i.e so if you create $scope.dataModel.dataProperty and use that in ng-model=dataModel.dataProperty (example) you again have two way binding ... you don't need to do anything as angular is taking care of the data pipeline. So if you want to extract the value to var, which is probably a waste as the $scope is already set as soon as the user checks the box
var formField = $scope.dataModel.dataProperty;
// but like I said no need as $scope.dataModel.dataProperty; is your var
In JS if you want to use a dynamic property as an object property key you would place the dynamic value in [] e.g.
$scope.variable[dynamicProperty].method;
// you can set a static property as a key with dot notation i.e.
$scope.variable.staticProperty = val;
Hope that helps
There is an object that contains a list of error messages: error code + error text. There is an array of error messages (array of error codes) I would like to display on the page (in some places) without any additional validation.
I've tried to do that here in jsFiddle with AngularJS, but seems like I could be on the wrong way of how to do it better as I'm new to AngularJS. That's why I'm asking SO community to think and to help, if that's look an interesting problem.
Here is a code below or check from jsFiddle.
Beside angular.js, angular-messages.js was added as well:
HTML:
<h3>So what I need here is actually to display errors that are returned by my custom showErrorsWeWant service. The array of errors can be different. No additional validation is needed. As result, I'm not sure if to stick with ng-message(s) or ng-if(s) (so both ng-message and ng-if are used in this example)</h3>
<h4>
As result, once the page is loaded, only 'You did not enter your name' and "'text for error04'" should be displyaed, based on
return ['error01', 'error04'];
</h4>
<h5>For three errors in returned array - then 3 respective errors displayed for these two inputs.
The very <u>IMPORTANT</u> thing: I don't know how to stick so each error know its place - is it for first input or for the second one. Still thinking how to make it done. Probably the additional property should be assigned in the json object.</h5>
<form name="myForm">
<label>Name:</label>
<input type="text" name="myName" ng-model="name" ng-minlength="5" ng-maxlength="5" required placeholder="type here" />
<div ng-messages="myForm.myName.$error" style="color:red; padding-left: 60px;">
<div ng-message="required">{{ errors['error01'] }}</div>
<div ng-message="minlength">{{ errors['error02'] }}</div>
<div ng-message="maxlength">{{ errors['error03'] }}</div>
</div>
</form>
<div id="statusBlock">
<label>City:</label>
<input type="text" placeholder="and type here">
<div style="color:red; padding-left: 60px;">
<div ng-if="errorsArr[1]=='error04'">{{ errors['error04'] }}</div>
<div ng-if="1<3">{{ errors['error05'] }}</div>
<div ng-message="maxlength">{{ errors['error06'] }}</div>
</div>
</div>
</div>
</body>
JS code:
var myApp = angular.module('myApp', ['ngMessages']);
myApp.controller('myController', ['$scope', 'showErrorsWeWant', function ($scope, showErrorsWeWant){
$scope.name = "";
$scope.errors= {
error01: 'You did not enter your name',
error02: 'Your name is less than 5 symbols',
error03: 'Yr name is 6+ symbols',
error04: 'text for error04',
error05: 'text for error05',
error06: 'text for error06'
}
$scope.errorsArr = showErrorsWeWant;
console.log($scope.errorsArr);
}]);
myApp.service('showErrorsWeWant', [function (){
return ['error01', 'error04'];
}]);
Please let me know if I've missed something. Thank you.
You can use an ng-repeat to create an element with ng-message for each one:
<div ng-messages="myForm.myName.$error" style="color:red; padding-left: 60px;">
<div ng-message="{{key}}" ng-repeat="(key, errorMessage) in errors">{{ errorMessage }}</div>
</div>
For this to work, the keys of your errors object must match the type of error:
$scope.errors= {
required: 'You did not enter your name',
minlength: 'Your name is less than 5 symbols',
maxlength: 'Yr name is 6+ symbols'
};
I am trying to do inline editing on a table of data (See the plunkr)
<table class="table table-bordered">
<tr ng-repeat="data in dataset" >
<td ng-repeat="(key, value) in data" >
<div class="key-block">
<strong >{{key}}</strong>
</div>
<div class="val-block" inline-edit="data[key]" on-save="updateTodo(value)" on-cancel="cancelEdit(value)">
<input type="text" on-enter="save()" on-esc="cancel()" ng-model="model" ng-show="editMode">
<button ng-click="cancel()" ng-show="editMode">cancel</button>
<button ng-click="save()" ng-show="editMode">save</button>
<span ng-mouseenter="showEdit = true" ng-mouseleave="showEdit = false">
<span ng-hide="editMode" ng-click="edit()">{{model}}</span>
<a ng-show="showEdit" ng-click="edit()">edit</a>
</span>
</div>
</td>
</tr>
I can see in many places that we have to use a . in ng-model inside ng-repeat to avoid the scope issue. As I dont know the key already I am doing like data[key] for the model.
The input field blurs after I enter a single character.
The behavior you described is normal. If you look closely you will see that both the input value and the directive are bound to the same object i.e data[key]. When you change the value of the text input the model get updated ultimately triggering a refresh of the directive and you are back to the "list" view.
One easy solution to fix this is to use an intermediate variable between the directive and the input value and update the model only when the save button is clicked. Something like that :
//Directive
scope.newValue = null;
scope.edit = function() {
scope.editMode = true;
scope.newValue = scope.model;
$timeout(function() {
elm.find('input')[0].focus();
}, 0, false);
};
//Template
<input type="text" on-enter="save()" on-esc="cancel()" ng-model="newValue" ng-show="editMode">
You can see a modified plunker here.