Angular JS - ng-repeat repeating old values - javascript

I am new to Angular JS. I have created a code in angular using app and controller. What I am tyring to do is to add name dynamically to a array when a button is clicked.
By default my array has two value passed. When i give an input and click the add button,it adds the string for the first time.
But when i give another input and click add again, the old string is replaced by the new string and the new string is added again.
Here is the piece of code on JSFiddle: http://jsfiddle.net/5DMjt/3680/
var demo= angular.module("demo",[]);
var simplecontroller = function($scope){
$scope.members = [{id:1,name:'prateek'},{id:2,name:'Ruchi'}];
$scope.addmember = function(newmember){
newmember.id = $scope.members.length+1;
$scope.members.push(newmeber);
demo.controller(simplecontroller);
}
}
and here is the HTML Code:
<div ng-app="demo">
<div ng-controller="simplecontroller">
<ul>
<li ng-repeat="member in members">{{member.id}}-{{member.name}}</li>
</ul>
Name<input type="Text" ng-model="inputmember.name">
</br><h2>
{{inputmember}}
</h2>
<input type="button" value="Add" ng-click="addmember(inputmember)">
</div>
</div>
Please Help !

What i analyzed is that push function is passing the address that is why binding still exists.What u can do is pass the value instead like i did below-:
$scope.addmember = function(newmember){
newmember.id = $scope.members.length+1;
$scope.members.push({id:newmember.id,name:newmember.name});
demo.controller(simplecontroller);
}
Hope this solves your problem.Happy learning :)

You have two options.
Either you can reinitialize it every time what I would not recommend.
And the other one is to, pass the parameters with values.
$scope.members.push({id:newmember.id,name:newmember.name});
:)

See this updated fiddle: http://jsfiddle.net/5DMjt/3689/
Name<input type="Text" ng-model="newname">
This gives you a scope variable newname.
<input type="button" value="Add" ng-click="addmember()">
And addmember function uses this newname to create a new object and add it to the list:
$scope.addmember = function(){
var newmember = {};
newmember.id = $scope.members.length+1;
newmember.name = $scope.newname;
$scope.members.push(newmember);
}

You have a syntax error. See console error for more info.
Your variable inputmember is not defined anywhere.
Also you need to push to array new reference of the object, so the old one in array does not change each time you type value.
Here is a working version.
http://jsfiddle.net/a9zvgm8k/
$scope.addmember = function(newMember){
newMember.id = $scope.members.length+1;
$scope.members.push(angular.extend({}, newMember));
demo.controller(simplecontroller);
}

$scope.members = $scope.members.concat({id: newmember.id, name: newmember.name});
Solved : http://jsfiddle.net/5DMjt/3693/

Before pushing to $scope.members you need to create a new object and populate it with id and name from the input.

Related

Populate Input Field using FormControl Angular

I have an input field where I need to populate array data inside it which is coming
from API, I have used FormControl to populate the data but not able to achieve the same.I am getting the response on console but not able to populate it on UI. Below is my code if any anyone could guide me as I have spent 2 entire days and new in Angular. Can anyone please help me here.
HTML Code:
<div formArrayName="ints" *ngFor="let inCompany of insurance.controls; let i = index">
<div [formGroupName] = "i">
<ion-card *ngFor="let eq of ef;let i=index;">
<ion-item>
<ion-input formControlName="iCompany"></ion-input>
</ion-item>
</ion-card>
</div>
</div>
TS Code:
ionViewWillEnter(){
this.loadData();
}
ngOnInit() {
this.sForm = this.formBuilder.group({
ints: this.formBuilder.array([]),
})
}
get ints(): FormArray {
return this.sForm.get('ints') as FormArray;
}
get formGroup(): FormGroup {
return this.formBuilder.group({
name: ['justTest'],
});
}
loadData(){
this.service.getefDetails(data).subscribe((response: any) => {
this.ef= response.data;
var formArray = this.sForm.get('ints') as FormArray;
for (let i = 0; i < this.ef.length; i++) {
console.log(this.ef.length, this.ef[i].percentage)
var chec=this.ef[i].percentage
formArray.push(this.formGroup);
formArray.controls[i].patchValue(chec);
}
)}
}
Array Type:
[{name:"test", percentage: "29"},{name:"abc", percentage: "45"}, {name:"def", percentage: "63"}]
First of all, I suggest you re-think your approach as mentioned in the earlier comment it seems you have made it unnecessarily complicated.
Also, I would think of renaming your variables it is quite confusing and will be a pain to maintain later on.
To answer your question and get the "ion-input" printed on the screen do the following changes to the HTML.
You can not assign <div [formGroupName] = "i"> i to the formGroup since it is not of type formGroup as it is assigned to the index.
The solution is to assign <div [formGroupName] = "insuranceCompany[0]">
So that a form group will be assigned.
Again I suggest that you rename the variable "insuranceCompany" for clarity purposes as there is a control named "insuranceCompany" as well.
Here is a working example of your code minus the ionic tags.
https://stackblitz.com/edit/angular-ivy-b3gtly?file=src/app/app.component.ts
Hope I made myself clear, and hope it helps.
You can use patchValue directly to an form control in order to do this.
Your current setup seems too complicated unless there are a bunch of other values in the form that's not displayed here.
However, when you get a response from API, you can simply get the reactive form element, and set value.
this.suitablityForm.insurance.insuranceCompany.patchValue('VAL_YOU_WANT');

why is my list not rendering?

by default it shows 10 elements, but when i change the input it does not update, below is the code and fiddle.
JS Code:
var app = angular.module('myapp',[]);
app.controller('ctrlParent',function($scope){
$scope.listItems = 10;
$scope.newTotal = function(){
$scope.$apply(function(){$scope.lisItemsTotal})
}
$scope.lisItemsTotal = function(num) {
return new Array($scope.listItems);
}
});
http://jsfiddle.net/0dwmqn8y/1/
The reason is that after changing the input $scope.listItems is a string, as the input type is text. Change it to number and all will work. Working plunker: http://jsfiddle.net/yv0z9q8L/
<input type="number" name="red" ng-model="listItems" onchange="angular.element(this).scope().newTotal()">
Also note, that you don't need onchange attribute at all here, however I am unsure whether this is a good thing. Using a function in for ng-repeat is quite dangerous unless you know what you are doing, as this function will be called in each digest cycle. If you are planning to loop over large set of data, it will pretty much kill your performance.
Personally, I would rather go with:
<div ng-app="myapp">
<div ng-controller="ctrlParent">
<input type="number" name="red" ng-model="itemCount">
<ul>
<li ng-repeat="i in items track by $index"><span>{{$index+1}}</span></li>
</ul>
</div>
</div>
var app = angular.module('myapp',[]);
app.controller('ctrlParent',function($scope){
$scope.$watch('itemCount', function(val) {
$scope.items = Array.new(val)
});
$scope.itemCount = 10;
});
plunker: http://jsfiddle.net/m1zq3zqv/1/
The data, that you get from the input field is a string, so you can either change the input type to number or apply a bit of parsing in your code by changing the following line
return new Array($scope.listItems);
to this:
return new Array(parseInt($scope.listItems));

edit update existing array in javascript

I am making CRUD app for learning purpose. I need to update existing javascript array on click of edit button. However currently its not updating the existing array rather then its creating new record. Below is the JS code of controller
For Add screen below is the controller code
.controller('addController', ['$scope','$location','$rootScope', function(scope,location,rootScope){
scope.save = function (){
scope.personName = document.getElementById('name').value;
scope.personDesc = document.getElementById('desc').value;
scope.person = {'name' : scope.personName, 'desc' : scope.personDesc};
if(typeof rootScope.crew === 'undefined'){
rootScope.crew = [];
}
rootScope.crew.push(scope.person);
location.path("/");
}
}])
For Edit Screen, below is the code of controller :-
.controller('editController',['$scope','$location','$routeParams','$rootScope', function(scope,location,routeParams,rootScope){
var oldName = scope.crew[routeParams.id].name;
document.getElementById('name').value = scope.crew[routeParams.id].name;
document.getElementById('desc').value = scope.crew[routeParams.id].desc;
scope.editSave = function(){
scope.person = {
'name' : document.getElementById('name').value,
'desc' : document.getElementById('desc').value
}
rootScope.crew.push(scope.person);
location.path("/");
}
}])
Currently I am adding record in existing array rather updating.
Please suggest
The problem is you are pushing a new item to the array. You need to just update the existing person with the person in scope.
.controller('editController',['$scope','$location','$routeParams','$rootScope', function(scope,location,routeParams,rootScope){
var person = scope.crew[routeParams.id]
scope.person = {
name = person.name,
desc = person.desc
};
scope.editSave = function(){
scope.crew[routeParams.id] = scope.person;
location.path("/");
}
}])
In your edit view you would have this:
<input type="text" id="name" ng-model="person.name"/>
<input type="text" id="desc" ng-model="person.desc"/>
It's also worth mentioning that there is no need to have code such as document.getElementById as angular will handle the model binding for you so you don't have to interact with the dom using javascript.
Every object that you are pushing in array must be identified by some id.So assign one id attribute to the person object that you are pushing.
Now come to the edit.html
<tr ng-repeat="p in person">
{{p.name}}
//In button I am passing id which I used in editing the person object
<button ng-click="edit(p.id)"></button>
</tr>
//In controller
edit(id){
//firstly search for the person which is going to be updated
for(i=0;i<arrayInWhichYouArePushingData.length;i++)
{
if(arrayInWhichYouArePushingData[i].id==id)
{
arrayInWhichYouArePushingData[i]=UpdatedData;
break;
}
}
This is just an algorithm to solve this type of problem.You have to modify little bit.

Conditionally setting orderBy Angularjs

I have an array of users, I want to have my ng-repeat ordered by last name when first loaded. After a new user is added have the ng-repeat ordered by dated added then last name. Essentially I want the newest users pushed to the top of the ng-repeat.
<th ng-click="menuFilter('lastName', 1);">
<div ng-class='{"menuSort":sortColumn==1}'>Name <span ng-show="share.orderByField == 'lastName'">
</div>
</th>
<tr ng-repeat="user in users | orderBy:orderByField:reverseSort"></tr>
In my JS...
_this.sortColumn = 1;
_this.orderByField = 'lastName';
_this.reverseSort = false;
_this.menuFilter = function(section, column) {
_this.orderByField = section;
_this.reverseSort = !_this.reverseSort;
_this.sortColumn = column;
};
//my attempt to reset the order by created at date
if( _this.isRefreshing ) {
_this.orderByField = ['createdAt', 'lastName'];
}
Basically this code is not doing anything. I think I am missing a step in the HTML.
Thanks!
I think this is easiest done by sorting the array in pure javascript and then using a ng-repeat without the orderBy attribute.
HTML:
<div ng-repeat="user in users">{{user}}</div>
<input type="text" ng-model="name"></input>
<button ng-click="addName()">Add name</button>
JS:
$scope.users = ["Rusty", "Shackleford", "Dale", "Gribble"];
$scope.users.sort();
$scope.addName = function() {
$scope.users.unshift($scope.name);
}
JSFiddle: http://jsfiddle.net/asWF9/2/
This answer may help to sort your array: https://stackoverflow.com/a/6712080/3675149
Try using "unshift" instead of 'push' to add an item into the array. The unshift in js enables us to insert an item to the top of an array.

Creating a function to edit a list with a variable number and given string

I am trying to create a function that takes two parameters, a number and a string. I need to be able to call it with a number, n, so that the nth element of theList will be modified to read as the string from the function.
I am a BEGINNER, so I am struggling with this -- I know that what I currently have in the function is NOT what I need, but I was hoping to use it as a starting point that I could adapt. I am thinking I probably need to use looping to do this...beyond that, I dont have many ideas. Any guidance?
<html>
<script>
function doit() {
document.getElementById('element1').innerHTML='Element one';
document.getElementById('element2').innerHTML='Element two';
document.getElementById('element3').innerHTML='Element three';
}
</script>
<body>
<p>Value: <input type="text" id="theInput" value="" size=10>
<input type="button" id="theButton" value="click me!" onclick="doit()"></p>
<ul id="theList">
<li id="element1">Element 1
<li id="element2">Element 2
<li id="element3">Element 3
</ul>
<div id="theDiv"></div>
</body>
</html>
You can use jQuery to get the children (li) element of the ul tag. It will return an array of all of the children. Note, the array is zero-indexed. You will need to keep this in mind when passing index in, or update the code to -1 from the index.
function updateListItem(index, text) {
var myListItem = $("#theList").children()[index]; // DOM reference to the list item
$(myListItem).text(text); // update the text
}
Without jQuery, you can do it something like this:
function updateListItem(index, text) {
var myListItem = document.getElementById("theList").children[index] // An array of the list items
myListItem.innerHTML = text; // update the text
}
Here are some ideas as to what you should do:
For function doit, you need to add two parameters representing the string and the number.
Next, create a variable that is the concatenation (string addition) of "element" and your number parameter
Finally, use your above method to set document.getElementById(<your string here>) to whatever your string was.
Here is an example of a quick implementation:
function doit(str, num){
var elementID = "element" + num;
document.getElementById(elementID).innerHTML = str;
}

Categories