This is my HTML code in angular template. In my controller I have
$scope.contacts.
Every contact in $scope.contacts can have multiple contact.fields. You can see I have 2 ng-repeat here, for every contact and every contact.field. User can add contact manually, and for every contact it is defined how many fields it has. So user click on plus and contact with empty fields is added. My question is: how to bind view with $scope.contacts, so when user adds new contact, it shows up in $scope.contacts?
<div id="contactsContainer">
<div id="{{contact.divId}}" ng-style="{'border': contact.borderStyle}"
class="form-group {{contact.divId}}" ng-mouseover="hoverIn()"
ng-mouseleave="hoverOut()" ng-repeat="contact in contacts track by $index">
<label class="col-sm-3 control-label">{{ translate[contact.keyTranslationName]}}</label>
<div id="fieldContainer" class="col-sm-4">
<div id="currentField" class="row mb5"
ng-repeat="field in contact.field track by $index">
<div id="{{contact.idPersonContact}}"
class="{{field.width}} has-icon pull-left">
<input name="{{field.name}}"
id="{{field.id}}"
placeholder="{{ translate[field.keyTranslationPlaceholder] }}"
class="form-control" value="{{field.value}}"
style="background-image: url();background-position: left;background-repeat: no-repeat;background-size:20px;">
</div>
</div>
</div>
</div>
<input type="button" ng-click="addContact()" />
// Controller
$scope.addContact = function(){
$scope.contacts.push({field : []});
// or field : Array(defaultFieldSize)
$scope.contacts.push({field : new Array(5) }); // Contact with 5 empty fields
}
Adding a contact in the contacts collection would do it. So when the user creates the new contact using the button you would do something like:
var newContact = {
field1:'',
field2: ''
...
}
and then just add the new contact to the contacts collection.
$scope.contacts.push(newContact);
ng-repeat will detect the change in the collection and render it.
Related
Hopefully a simple Angular binding question.
I have a TextBox on my Angular 4 [x.component.html] that has an (input) event tied to it, so each time the user types in a character into the textbox it reaches out to a method in the [x.component.ts] typescript file - which then retrieves data from a service to populate a local array of data in the typescript file - which is bound to a dropdownlist on the [x.component.html]. This process functionally works fine.
However the problem I am having is that when it updates the data in the local array, it is not clearing out the previous data in the dropdown, so the dropdown list ends up getting populated with lots of duplicate data. Has anyone experienced this same problem before? The local array of items seems to have the correct number of items in it, it just seems to keep populating the dropdownlist with the items without ever clearing the previous.
Thanks so much for your help.
Please note I have cut the code down to only the relevant parts for brevity.
[x.component.ts]
export class CreateComponent {
testService: TestService;
valueList: testValue[];
constructor(testService: TestService) {
this.testService = TestService;
}
ngOnInit() {
}
FieldChanged(event: any, controlNameToPopulate: string){
if (event.target.value.length >= 9) {
this.testService.getRecords(event.target.value).subscribe((data: any[]) => {
if (data.length != 0){
document.getElementById(controlNameToPopulate).hidden = false;
//this.valueList.slice();
this.valueList = data;
}
});
}
}
}
[x.component.html]
<div class="row">
<div class="col-md-6">
<nb-card>
<nb-card-header>Testing with Updating dropdownlist</nb-card-header>
<nb-card-body>
<form [formGroup]="formGrp">
<div class="form-group row">
<label class="col-sm-3 col-form-label">Quick search</label>
<div class="col-sm-9 input-group">
<input type="text" class="form-control input-sm" style="width: 50%" id="txtbx_ValTest" formControlName="testVal" (change)="FieldChanged($event, 'ddValuesToUpdate')">
<select id="ddValuesToUpdate" class="btn btn-secondary dropdown-toggle" style="width: 50%" hidden>
<option *ngFor="let val of valueList" [value]="val.id">{{val.id}}</option>
</select>
</div>
</div>
<div class="form-group row">
<div class="offset-sm-3 col-sm-9">
<button type="submit" class="btn btn-success pull-right">Add</button>
</div>
</div>
</form>
</nb-card-body>
</nb-card>
</div>
</div>
I'm new to angularjs / ionic and I try to create an ionic-app that posts IDs of prodcuts to a webserver. I have to display multiple <form> on one page with checkboxes (..and other types like select).
When I submit the first form everything works as expected. But when I try to submit a second form, the scope contains values from the first and from the second form. When i submit an empty form it also submits the values from the first form. Is there a way to "clean" the scope after every submit? How can I assure that the submit-button only submits values from its own form?
This is the <form> :
<form ng-submit="addCartFive()" name="type5_{{item.ID}}">
<div class="row">
<div class="col col-80"><strong>{{item['name']}}</strong> <br/>
{{item['description']}}
</div>
</div>
<div ng-repeat="variant in item.variants">
<ion-list ng-repeat="detail in variant.details">
<ion-checkbox name="sub-{{$index}}" ng-true-value="{{detail.ID}}" ng-model="formDataObjFive[$index][detail.ID]">
{{detail.name}} <span class="right">+ {{detail.price}}</span>
</ion-checkbox>
</ion-list>
</div>
<div class="row">
<button type="submit" ng-click="setValueFive(formDataObjFive)">order</button>
</div>
</form>
this is the relevant part of my controller:
$scope.setValueFive = function(a1) {
$scope.formDataObjFive = a1;
};
$scope.addCartFive = function () {
console.log($scope.formDataObjFive);
CartService.save($scope.formDataObjFive) // send the values to factory wich posts to server
};
This is my code.
$scope.data=[];
$scope.data=[{"label":"name","type":"string"},{"label":"email","type":"string"}];
$scope.addFields = function (field) {
$scope.data.push(field);
};
This is my html:-
<div ng-repeat="eachItem in data">
<input type="button" value="add" ng-click="addFields(eachItem)"/>
<label>{{eachItem.label}}</label>
<input type="text" ng-model="fieldValue"/>
</div>
when i click add button push one more object into $scope.data array like
$scope.data=[{"label":"name","type":"string"},{"label":"email","type":"string"},{"label":"name","type":"string"}];
In the above i got an error
angular.min.js:102 Error: [ngRepeat:dupes] http://errors.angularjs.org/1.3.14/ngRepeat/dupes?p0=nestedField%20in%20fieā¦%2C%22type%22%3A%22string%22%2C%22%24%24hashKey%22%3A%22object%3A355%22%7D
at Error (native)
I have duplicate objects after adding. because i want to repeat label names using ng-repeat in angularjs.First i have output like this
OutPut:-
name textbox
email textbox
After add button click Output:-
name textbox
email textbox
name textbox
use track by $index
var app = angular.module("app",[])
app.controller('ctrl',['$scope', function($scope){
$scope.data=[];
$scope.data=[{"label":"name","type":"string"},{"label":"email","type":"string"}];
$scope.addFields = function (field) {
$scope.data.push(field);
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div class="item item-checkbox">
<div ng-repeat="eachItem in data track by $index">
<input type="button" value="add" ng-click="addFields(eachItem)"/>
<label>{{eachItem.label}}</label>
<input type="text" />
</div>
</div>
Use track by for this purpose.
<div ng-repeat="eachItem in data track by $index">
<input type="button" value="add" ng-click="addFields(eachItem)"/>
<label>{{eachItem.label}}</label>
<input type="text" ng-model="eachItem.value" />
</div>
You also able to use track by with your custom filed, like id, or whatever
Important: It's better to use track by in each ng-repeat, cause it's improve ng-repeat's performance (read more).
But avoid to use track by in ng-options and other cases when you use select as .. for ... construction (read more)
JsFiddle here
You have to ensure that items in the array have an unique key. If that is not possible you can use track by $index in the ng-repeat.
Check the details here
I am taking information from my database and trying to figure the best way to display it within the app.
This is my database info
[{"form_input_id":"1","form_id":"6","title":"Please enter your room number?","input_type":"text","identifer":"room","choices":"s:0:\"\";","heading":"Valet Request"},{"form_input_id":"2","form_id":"6","title":"Please enter any comments or feedback.","input_type":"textarea","identifer":"feedback","choices":"s:0:\"\";","heading":"Valet Request"},{"form_input_id":"3","form_id":"6","title":"Please choose office","input_type":"select","identifer":"office","choices":"s:19:\"Sales, Reservations\";","heading":"Valet Request"},{"form_input_id":"18","form_id":"6","title":"Last Name","input_type":"text","identifer":"Last_Name","choices":"s:0:\"\";","heading":"Valet Request"},{"form_input_id":"19","form_id":"6","title":"Type of Car","input_type":"select","identifer":"Car_type","choices":"s:20:\"Buick, Olds, Ferrari\";","heading":"Valet Request"}]
I am able to pull everything the way I want to except choices. I am trying to create dynamic forms and need to create a select showing the choices.
My current controller:
controller('FormCtrl', function($scope, $ionicLoading){
// Grab Form
var form = angular.fromJson(window.localStorage.getItem('form'));
// Set Title
$scope.title = form[0].heading;
// Send Form Data
$scope.forms = form;
})
And my view:
<ion-view title="Form" hide-nav-bar="true">
<ion-header-bar align-title="left" class="bar-dark">
<div class="buttons">
Cancel
</div>
</ion-header-bar>
<ion-content id="dynamic" scroll="true" padding="true">
<h2 class="text-center">{{title}}</h2>
<form>
<div ng-repeat="form in forms">
<label>{{form.title}}</label>
<div ng-if="form.input_type == 'text'">
<input type="text" name="{{form.identifier}}" />
</div>
<div ng-if="form.input_type == 'time'">
<input type="time" name="{{form.identifier}}" />
</div>
<div ng-if="form.input_type == 'textarea'">
<textarea name="{{form.identifier}}"></textarea>
</div>
<div ng-if="form.input_type == 'select'">
<select name="{{form.identifier}}">
NEED TO FIGURE HOW TO DISPLAY CHOICES AS OPTIONS
</select>
</div>
</div>
</form>
</ion-content>
You need to parse your options from string. Something like that:
angular.forEach($scope.forms, function(item){
item.options=item.choices.split('"')[1].split(',');
});
And tnen use ng-options in select:
<select name="{{form.identifier}}" ng-options="choice for choice in form.options" ng-model="Your model here"></select>
https://docs.angularjs.org/api/ng/directive/ngOptions
I am trying to fetch Roles data(JSON) from a url and using ng-repeat to assign it to radio buttons(shows list of roles) and display it in MODAL. Any one option must be selected for the role currently assigned to the user.
When a user changes the selection and clicks ok, selected value should be assigned to an object, which is further passed to a URL to update the role of user.
If i use,
<div ng-repeat="item in roleDataList">
<input type="radio" ng-model="item" ng-checked="item.RoleId==assignedRoleId?true:null" name="RoleRadioButton" ng-value="item" />
<span>{{item.RoleName}}</span>
</div>
then it shows the already assigned data as default but i cant access the selected data,
If i use,
<div ng-repeat="item in roleDataList">
<input type="radio" ng-model="$parent.parentRoleId" ng-checked="item.RoleId==assignedRoleId?true:null" name="RoleRadioButton" ng-value="item" />
<span>{{item.RoleName}}</span>
</div>
then selected role is available in $parent.parentRoleId, but default value is not selected.
Any help where both can be achieved?
Check out this fiddle pretty much what you want i think
Fiddle
<div ng-controller="Ctrl">
<span ng-repeat="category in categories">
<label class="checkbox" for="{{category.id}}">
<input type="checkbox" ng-model="selection.ids[category.id]" name="group" id="{{category.id}}" />
{{category.name}}
</label>
</span>
<pre ng-bind="selection.ids | json"></pre>
function Ctrl($scope) {
$scope.selection = {
ids: {"50d5ad": true}
};
$scope.categories = [ { "name": "Sport", "id": "50d5ad" } , {"name": "General", "id": "678ffr" } ];
}