I read through some articles on angular model binding, and just out of curiousity, I was wondering if its possible to bind keys to input too,
http://jsfiddle.net/x3azn/jM28y/4/
so I am hoping ot update the main arr through the input boxes and achieve 2 way key-binding.
Is this possible?
as explained here Binding inputs to an array of primitives using ngRepeat => uneditable inputs, yes you can, but not that way
try this
function ctrl($scope) {
$scope.arr = [{name:'1', lastname: '2'},
{name:'3', lastname: '4'},
{name:'5', lastname: '6'}]
}
<div ng-repeat="person in arr">
<input type="text" ng-model="person.name" />
<input type="text" ng-model="person.lastname" />
</div>
http://jsfiddle.net/jM28y/5/
No, it is not possible to bind a key to an input.
The closest thing that I found you can do is abuse ngRepeat's $index property and bind it to the input. You can't change keys for existing values but you can change what value is shown as well as create new key-value pairs. By no means am I recommending this as a solution, I just wanted to share the hackery that ensued when I was investigating this question.
JSFiddle: http://jsfiddle.net/DanielBank/v6tFG/
JavaScript:
function ctrl($scope){
$scope.obj = {
'0': 'a',
'1': 'b',
'2': 'c',
'George': 'Clooney',
};
}
HTML:
<div ng-app>
<div ng-controller="ctrl">
<div ng-repeat="value in obj">
<input type="text" ng-model="$index"/>
<input type="text" ng-model="obj[$index]"/>
<input type="text" ng-model="value"/>
</div>
{{obj}}
</div>
</div>
Related
I want to be able to add/remove items in an order and have them aggregate into an array to be sent to the backend. The data will look like:
CustomerName: Billy
Orders: [Pizza, Burger, Sushi]
Can't find any SO answers or documentation that gets into iterated input binding. Anyone attempted this? Template code:
<div>
<input
type="text"
name="name"
title="name"
placeholder="Customer Name"
[(ngModel)]="customerName"/>
</div>
<div *ngFor="let item of itemsInNewOrder; let i = index">
<input
type="text"
name="order"
title="order"
[(ngModel)]="itemsInNewOrder[index]"/>
</div>
inside the Add New button's click function:
...firebaseStuff... .push({name: name, order: this.itemsInNewOrder})
unfortunately, this doesn't work. Thanks in advance! :)
Edit 1: There are 2 buttons that trigger (respectively):
incrementItemsInNewOrder() {
this.itemsInNewOrder.push("")
}
decrementItemsInNewOrder() {
this.itemsInNewOrder.pop()
}
I can see one problem. You should use the variable i that you have declared in template.
<div *ngFor="let item of itemsInNewOrder; let i = index">
<input
type="text"
name="order"
title="order"
[(ngModel)]="itemsInNewOrder[i]"/> <------ HERE
</div>
EDIT
angular seems to be doing change detection when typing into the inputs and renders them again, when that happens you lose the focus.
but if you wrap the values into objects and suddenly it works.
Component:
itemsInNewOrder = [{value: 'Soda'}, {value: 'Burger'}, {value: 'Fries'}];
template:
<div *ngFor="let item of itemsInNewOrder; let i = index">
<input
type="text"
name="order"
title="order"
[(ngModel)]="itemsInNewOrder[i].value"/>
</div>
I have a object which holds the key and value pair.
$scope.groups= {
1050 : 'Test',
1850 : 'Test1'
}
$scope.AnotherArray = [1050,1850];
item from ng-repeat is passed to the object as key to obtain the text 'Test'
<div ng-repeat="item in AnotherArray">
<input type="text" ng-model="groups[item]" />
</div>
Is there a way in angular to do this ?
As you were asking for an "Angular-way" to do this, here is a mildly modified version of Angular's ngRepeat example:
<div ng-repeat="(key, obj) in groups">
[{{key}}] {{obj}}
<input type="text" ng-model="obj"/>
</div>
http://plnkr.co/edit/0IRvLZpbUZUQBXOnebOt?p=preview
It makes use of Angular's internal conversion of array-like objects.
Link to Angular's ngRepeat-documentation: https://docs.angularjs.org/api/ng/directive/ngRepeat
I have an array of strings, and I want each of the strings to be bound to an input.
However, editing the input doesn't seem to update the array (isolated scope issues maybe?).
Suggestions?
function Ctrl($scope) {
$scope.fruits = ['Apple', 'Mango', 'Banana', 'Strawberry'];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="Ctrl">
<div style="margin: 20px 0" ng-repeat="fruit in fruits">
<input type="text" ng-model="fruit" />
</div>
Fruits: {{fruits}}
</div>
</div>
You need the array reference which you can get from $index. Note however that this won't work if any filtering is done on the ng-repeat as the indexing then is based on filtered array not the original
<div style="margin: 20px 0" ng-repeat="fruit in fruits track by $index">
<input type="text" ng-model="fruits[$index]" />
</div>
DEMO
Ok, so it seems to me like a case of
'ng-model requires a dot in the model name to work correctly with the
scope, otherwise it would create a local scope'
What i would suggest is to change your data structure from plain strings to objects containing the strings as a property, something like :
$scope.fruits = [
{'title':'Apple'},
{'title':'Mango'},
{'title':'Banana'},
{'title':'Strawberry'},
];
Now, when you bind it to ng-model like this
<div style="margin: 20px 0" ng-repeat="fruit in fruits">
<input type="text" ng-model="fruit.title" />
</div>
then it will not create any local/child scope, instead it would be able to bind to the title property on the items in the fruits array.
example fiddle: http://jsfiddle.net/HB7LU/24008/
I have a requirements, in which I have to show a combo-box (select). The options in it aren't fixed, I need to give a link to add more options, on whose click a text box must be shown within the select element, user will enter a value and it will be added in select's options. Please tell me how this can be achieved using Angular. jQuery provides a way to do that, but if i use that I am not able to bind the elements with Angular.
Regards
Nitin
Javascript file:
function ctrl($scope){
$scope.rows = ['Paul','John','Lucie'];
$scope.addRow = function(){
$scope.rows.push($scope.addName);
$scope.addName = "";
};
}
HTML page:
<body ng-controller="ctrl">
<select>
<option ng-repeat="row in rows" value="{{ row }}">{{ row }}</option>
</select>
<span class="input-append">
<input id="add" type="text" placeholder="Another one ?" ng-model="addName" />
<input type="submit" class="btn btn-primary" ng-click="addRow()" value="+ add" />
</span>
</body>
See: http://codepen.io/anon/pen/JdqqXj
I'd suggest that you take a look at the docs dedicated to the select control in AngularJS. In a nutshell, you can use the ngRepeat to generate the options for you. If you need to get them from a backend, you can use resolve in your routing options and a service to grab them for you.
The example by AngularJs's website:
HTML
<div ng-controller="ExampleController">
<form name="myForm">
<label for="repeatSelect"> Repeat select: </label>
<select name="repeatSelect" ng-model="data.repeatSelect">
<option ng-repeat="option in data.availableOptions" value="{{option.id}}">{{option.name}}</option>
</select>
</form>
<hr>
<tt>repeatSelect = {{data.repeatSelect}}</tt><br/>
</div>
APP.JS
angular.module('ngrepeatSelect', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.data = {
singleSelect: null,
availableOptions: [
{id: '1', name: 'Option A'},
{id: '2', name: 'Option B'},
{id: '3', name: 'Option C'}
],
};
}]);
You can also use ng-options, which is more recommended.
In regards to the textbox element, associate the two elements with ng-model.
Example:
Note: I'm quite new to angularjs
What is the best solution/practice for problem:
I have an array or typed values, for each type there should be different input(template and input validation)?
E.g. and simplified
var vars = [
{
type: 'int',
value: 42,
min: 0,
max: 42
},
{
type: 'text',
value: 'foobar'
},
]
for 'int' template will be
<input type="range" max="{{max}}" min="{{min}}" value="{{value}}" />
and for 'text'
<textarea>{{value}}</textarea>
In real case there will be quite many inputs with weird interfaces
An ng-switch (docs) can help you out here; something like this:
<div ng-repeat="item in items">
<div ng-switch on="item.type">
<div ng-switch-when="int">
<input type="range" max="{{item.max}}" min="{{item.min}}"
ng-model="item.value" />
</div>
<div ng-switch-when="text">
<textarea ng-model="item.value"></textarea>
</div>
</div>
</div>
[Update]
Since you mentioned you want to dynamically include a template based on the type, take a look at ng-include (docs) which takes an Angular expression evaluating to a URL:
<div ng-repeat="item in items">
<div ng-include="'input-' + item.type + '-template.htm'"></div>
</div>
If you don't like the inline string concatenation, you can use a controller method to generate the URL:
<div ng-repeat="item in items">
<div ng-include="templatePathForItem(item)"></div>
</div>
The example on the ngInclude documentation page is pretty good.
Note that the included template will be given a prototypal child scope of the current scope.