adding an array property to object in angular js - javascript

I have an object called user:
It has properties like user.name, user.age e.tc.
Now, I need to add an array to user object called subjects via ng-model.
This is what i did inside of ng-repeat:
<input type="text" ng-model="user.subjectname[$index]"
name="subject" ng-required="true" placeholder="Enter a subject name">
and when I do console.log(user.subjectname), it looks like this:
Now, after this, I wanted to do something like this:
<div ng-repeat="data in user.sujects">
<td>{{data}} </td>
</div>
But it does not work.
Try2:
In my my service that is called from controller, I tried this,
if(dataArray== null)
var dataArray=[];
console.log("scop.user.subjectname...................." + user.subjectname);
for(var i in user.subjectname)
{ dataArray.push(user.subjectname[i])
}
user.data=dataArray;
so, now if I do,
<div ng-repeat="data in user.data">
<td>{{data}} </td>
</div>
I still get nothing.
Can I get some direction to deal with this?

Like I told you in your previous question, and showcased in a jsbin.
You need to use the (key, val) in object syntax to get those values out of user.subjectname
ng-repeat="(key, val) in user.subjectname" ng-bind="val"
If you need to transform this object into an array:
$scope.arr = [];
Object.keys(user.subjectname).forEach(function (key) {
arr.push(user.subjectname[key]);
});
Then if you need to output that
ng-repeat="a in arr" ng-bind="a"
edit: after further explanation from you, I'm assuming this jsBin highlights something close to what you are after.

Related

watch the value in angularjs

how to watch the array value of ng-model in angularjs i have created fiddle but does not work Please take a look and suggest.
Thanks
<div ng-app ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl">
<table>
<tr ng-repeat="user in profiles track by $index">
<td>
<input
type="text"
name="parktime_{{user.user_id}}"
ng-model="orderItems[user.user_id].parktime"
>
</td>
</tr>
</table>
</div>
</div>
function ParentCtrl($scope) {
}
function ChildCtrl($scope) {
$scope.parkOptions = {};
$scope.profiles = [
{user_id: '01', park_name: 'England Park'},
{user_id: '02', park_name: 'France Park'}
];
$scope.orderItems = {};
$scope.orderItems.parktime = "Test";
$scope.$watch('orderItems[profiles.user_id].parktime', function(newVal, oldVal){
console.log(newVal);
})
}
http://jsfiddle.net/w5vskLfc/59/
I suggest you use ng-change instead. You can't use watch this way, it is to watch a single property instead.
I've also updated your model to use ng-init. This is something you should be careful with using, but in your case, you need to have an key defined at each position of your orderItems object. If you will always statically assign these, I recommend iterating through them once and creating a key that way instead.
HTML
<input type="text" name="parktime_{{user.user_id}}"
ng-init="orderItems[user.user_id] = {}"
ng-model="orderItems[user.user_id].parktime"
ng-change="onChange(user.user_id)">
JS
$scope.onChange = function(items) {
console.log(items);
}
You are trying to access indexes which does not exist. profiles is an array of objects and I don't think there is anything available on profiles.user_id index. Also, I don't think orderItems[profiles.user_id] will work as that index also doesn't exist.

AngularJS creating json from ng-repeat

Inspired from this codepen I used a JSON file to load some basic input fields and toggles. When the user change something and press save, I would like to save these new property values in a new JSON object with same property names.
My code looks the this
JS
.controller('page', function($scope, templateSettingsFactory, savedSettingsFactory) {
$scope.template = templateSettingsFactory;
$scope.saved = savedSettingsFactory;
$scope.saveSettings = function(){
var temp = $scope.template;
var jsonObj = {};
for(var key in temp){
jsonObj[key]=temp[key];
}
$scope.saved.$add(jsonObj);
};
});
HTML
<label ng-repeat="item in template">
<input type="text" placeholder="{{item}}">
</label>
<button class="button" ng-click="saveSettings()">Save</button>
The problem is that calling the saveSettings() don't get the updated property values of $scope.template - perhaps it's not doing two-way binding?
You need to use ng-model on your form elements to bind their input to the scope.
<input type="text" ng-model="item.property">
Here is an example of binding to a single object with arbitrary keys:
<div ng-repeat="(key,value) in template">
<div>{{key}}</div>
<input type="text" ng-model="template[key]"/>
</div>
https://docs.angularjs.org/api/ng/directive/ngModel

Get $id from nested ng-repeat

I have a post/comment system in Angularjs and Firebase, I can loop without problem to show all the post with ng-repeat and its comments as well. The problem start when I tried to get the $id from the second nested ng-repeat to be able to save the replies into the comment. Let's see the code I have:
<div class="posts" ng-repeat="post in posts">
<div>{{post.text}}</div>
<div>
<input type="text" placeholder="Comment here..." ng-model="comment">
<button ng-click="addComment(post, comment)"></button>
</div>
<div class="comments" ng-repeat="cmt in post.comments">
<p>{{cmt.text}}</p>
<div>
<input type="text" ng-model="answer">
<button ng-click="addAnswer(cmt, post)"></button>
</div>
<div ng-repeat="answer in cmt.answers">
<p>{{answer.text}}</p>
</div>
</div>
</div>
app.js
$scope.addComment = function(post, comment){
var ref = new Firebase("https://url.firebaseio.com/users/" + post.$id + "/comments");
var comments = $firebaseArray(ref);
comments.$add({
text: comment
});
}
$scope.addAnswer = function(cmt, post){
var refanswers = new Firebase("https://url.firebaseio.com/users/" + post.$id + "/comments/" + cmt.$id + "/answers");
var answers = $firebaseArray(refanswers);
answers.$add({
text: answer
});
}
To test, first I remove the code above inside addAnswer function and write two console.log to check if Im getting the values
console.log(post.$id);
console.log(cmt.$id);
I get only the post.$id but no the second one (undefined), am I missing something about nested ng-repeat?
Edited: I changed the code to avoid the $scope conflict following the answers below but still does not work.
Any advice is welcome, thanks :)
comment being passed into addAnswer() is likely not the instance object of the ng-repeat as you are thinking, rather it could be clashing with the ng-model='comment' already defined above. You have a scope issue.
This may be fixed by changing ng-repeat="comment in post.comments" to ng-repeat="cmnt in post.comments"or whatever you want to name it, as long as it doesn't conflict with previously defined $scope objects.

Parsing JSON result to object by using checkbox

I have loaded a JSON list into a table and I would like to parse 1 JSON result or multiple results into an object, so I can send it to the server.
My table looks like this so far:
HTML
<tr ng-repeat="t in student">
<td ng-model="herkanserNaam">{{ t.Name }}</td>
<td>{{ t.City }}</td>
<td>
<div class="checkbox" ng-click="laatzien(herkanserNaam, herkanserCheck)" ng-model="herkanserCheck">
<label>
<input type="checkbox">
</label>
</div>
</td>
</tr>
Controller
$scope.laatzien = function(name, active) {
var herkanser = [{
"name" : name,
"active" : false
}];
console.log(herkanser);
}
How would I be able to check one or multiple results and save the data(t.Name) into an object by using a checkbox? So far the function laatzien() is returning the empty values defined in herkanser.
The reason your laatzien method is failing is due to how you are using your directives. Let's work with the example you provided to get your laatzien method to fire.
HTML
<tr ng-repeat="student in students">
<td>{{ student.Name }}</td>
<td>{{ student.City }}</td>
<td>van</td>
<td>Huis</td>
<td>j.huis#student.han.nl</td>
<td>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="student.isActive" ng-change="laatzien(student)">
</label>
</div>
</td>
</tr>
Javascript
$scope.laatzien = function (student) {
var herkanser = [{
"name": student.name,
"active": student.isActive
}];
console.log(herkanser);
}
I have made some opinionated changes in your example for readability purposes, others were needed to get the directives to fire as expected. Below are the changes to your snippets.
Renamed the student array to students. This will require a change in your controller from $scope.student to $scope.students.
Renamed the t object to student.
Removed the ng-click directive from your div.
Added an ng-change directive on your checkbox. Now when you click the checkbox your laatzien method should fire.
Added an isActive property to your student. Inside of your laatzien method, you may now check the state of the checkbox. If the checkbox is checked, student.isActive = true. If the checkbox is not checked, student.isActive = false.
From your code, you seem to want to build the "list of checked students" and send that to the server. In other words, what you want, is to allow the user to check on multiple students and at the end collect everything that was checked and send it over to the server.
If that's the case then your strategy to put an ng-click over the checkbox is wrong.
What you need is to bind your checkbox to your $scope model. Such as this:
<input type="checkbox" ng-model="t.isChecked" ng-true-value="true" ng-false-value="false'">
When the user checks the checkbox for a student. Your model will automatically be updated.
To collect the data to send over the server you need to put an ng-click on a submit button. In the event handler, simply loop through every student in your $scope "students" model and only save the ones that have isChecked property to true to be sent over to the server.
Hope this helps!
You could make a function to push thet item into an obj like so...
$scope.students = [
{
"name":"John",
"city":"Boston"
},
{
"name":"Amy",
"city":"Dallas"
}
]
$scope.activeObj = [];
$scope.laatzien = function(obj) {
if($.inArray(obj, $scope.activeObj) == -1) {
$scope.activeObj.push(obj);
} else {
var index = $scope.activeObj.indexOf(obj);
$scope.activeObj.splice(index, 1);
}
}
http://jsfiddle.net/5fcnazb2/

Filter separate variable in Angular

So I have some code that looks like this:
<input ng-model="search" type="text">
<td ng-repeat="key in targets">
{{ display_names[key] }}
</td>
To be more clear:
targets is a variable containing not-human readable ids such as key012
display_names is an object which has keys like: key012: "USA"
I would like to filter the display_names value from the search? Looking at the angularjs docs, I know I can filter key, but I haven't figured out how to filter display_names
Example
Here's a full example:
var TS = angular.module('myapp', []);
TS.controller('test', function($scope) {
$scope.targets = ["id_1", "id_2"];
$scope.display_names = {
"id_1": "USA",
"id_2": "Mexico"
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myapp" ng-controller="test">
<input ng-model="search" placeholder="Search...">
<ul>
<li ng-repeat="key in targets">{{display_names[key]}}</li>
</ul>
</body>
<td ng-repeat="key in targets">
<span ng-if="display_names[key].indexOf(search) > -1">{{ display_names[key] }}</span>
</td>
use ng-if, or you could also use ng-show. Differences here
This way, as you write in search (which should be in $scope.search) angular will refresh the ng-repeat values to show
If you want to search it case-insensitive, you could use toLowerCase() function before using indexOf
display_names[key].toLowerCase().indexOf(search) > -1
You can't use a filter | in the html because you don't have the value you want to filter against in the array you are iterating over. Instead you can use ng-if to show/hide the elements based on the search. Something like:
<div ng-repeat="key in targets" ng-if="!search || !!display_names[key].match(search)">
{{ display_names[key] }}
</div>
The !! boolean cast is done because otherwise a new Regex object will be returned for the match which triggers a digest cycle which will return another new object and so on.
You also probably want to iterate over <tr> rather than <td>, and you need a <table> element for these elements to be allowed.
Example: http://plnkr.co/edit/qrpLKD9x4IBXowpIgnrf?p=preview
You could also write a custom filter for this, but it is a lot more work:
.filter('displayNames' function () {
return function (key, names, search) {
return !search || !!names[key].match(search);
};
});
And use it like key in targets | displayNames:display_names:search

Categories

Resources