Pass data to ui-grid inside ng-repeat in Angular - angularjs

I'm new to Angular and have been searching for a was to pass data from an iteration inside ng-repeat to a table that ui-grid is making.
I have a JSON-object which is structured similar to this:
{
category1: {obj{atr1: val, atr2:val}, obj2{atr1: val, atr2:val}},
category2: {obj{atr1: val, atr2:val}, obj2{atr1: val, atr2:val}}
}
I'm using ng-repeat to iterate over it similar to this:
<div ng-repeat="(category, objs) in jsonObj">
<h3>{{category}}</h3>
<div ui-grid="{ data: objs}" class="grid"></div>
</div>
This works for displaying the category name () but I can't figure out how to pass the objs to ui-grid. What is the right way to do this? Can I make a function and call it through data: and get the data that way? If I use just gridOptions and define the data in the .js all tables will get the same data, can I pass some variable from where the tables are being iterated so I can chose the correct data for each?

Figured it out!
<div ng-repeat="(category, objs) in jsonObj">
<div ui-grid="{ data: jsonObj[category] }" class="grid"></div>
</br>
</div>
This along with making the corresponding values lists (thanks MMhunter) works.

Related

Binding raw object output to a form representation

I'm trying to update models from a JSON representation of an object to a form. Here's a link to an example
To recreate my issue,
Change the data in the form (see that the JSON changes).
Change the JSON (See that the form doesn't change).
Here's my code:
JS
var ppl = {
createdby: "foo",
dateCreated: "bar",
}
angular.module('myApp', [])
.controller("Ctrl_List", function($scope) {
$scope.people = ppl
$scope.print = JSON.stringify($scope.ppl)
})
HTML
<div ng-app="myApp">
<div class="container" ng-controller="Ctrl_List">
<!-- FORM -->
<div class="row" ng-repeat="(key,val) in people track by $index">
<div class="col-md-12">
<label for="{{key}}">{{key}}</label>
<input class=form-control" id="{{key}}" ng-model="people[key]">
</div>
</div>
<!-- JSON -->
<div class="editable" contenteditable="true" ng-model="people">{{people}}</div>
</div>
</div>
When a user changes the JSON, the form should update in real-time.
Here's some things I have tried:
Change the JSON display element from div to input but it prints [Object][Object]
Also <input ng-model="JSON.stringify(people)"> but I get an "unbindable element" error.
Also tried adding a new model: $scope.print = JSON.stringify(people) but it shows nothing in the raw output.
Is it even possible to update a live object or am I gonna have to do some sort of event that triggers the form to change?
PS: Angular 1.5.8
There are several reasons why this doesn't work:
ng-model on a div doesn't do anything
even if it did, it would save a string to people, and your form would thus not work anymore.
You should use a textarea to make it work, and bind it to another variable, of type string. Using ng-change on the textarea, and on the inputs of the form, allows populating the people object by parsing the JSON string, and vice-verse, populating the JSON string from the people object.
See https://codepen.io/anon/pen/peexPG for a demo.
Refering to Contenteditable with ng-model doesn't work,
contenteditable tag will not work directly with angular's ng-model because the way contenteditable rerender the dom element on every change.

Assigning a filter to an object variable in Angular JS

I have an ng-repeat using a filter like this:
#1
<div class="contestReports" ng-repeat="contest in contests | filter:{votingOver:true}">
<contestreport></contestreport>
</div>
I want to allow the customer to be able to filter it so I have assigned the filter to a variable like this:
#2
<div ng-init="reportFilter = {votingOver:true}"></div>
<div class="contestReports" ng-repeat="contest in contests | filter:reportFilter">
<contestreport></contestreport>
</div>
Code #1 is working but Code #2 is not and I'm not sure why.
Did you also try to wrap ng-init
<div ng-init="(reportFilter = '{votingOver:true}')"></div>
However, as I've stated in my comment earlier - angularjs documentation states that using ngInit is a bad practice in mostly all cases. So that should not be a solution to your problem if possible.
And your #2 code actually works, please check this plunk - http://plnkr.co/edit/dBDyYPd3ZoUVdXngu52t?p=preview
//html
<div ng-init="reportFilter = {votingOver:false}"></div>
<div class="contestReports" ng-repeat="contest in contests | filter:reportFilter">
{{contest | json}}
</div>
</div>
//js in controller
$scope.contests = [
{id:1, title:'1', votingOver:false},
{id:2, title:'2', votingOver:true},
{id:3, title:'3', votingOver:true}
];
Using ng-init is not a good way to go with(as you can see angular docs has added warning text in red). As you know it is going to evaluate on initial rendering only(as ng-init evaluates its expression in preLink phase).
By looking at your code, it seems like reportFilter variable is going to be an common object for all contests. Correct me if I'm wrong?
I'd add this value inside a controller only once like below.
//place this inside your controller
$scope.reportFilter = { votingOver : true };
And use directly on view itself.
<div class="contestReports" ng-repeat="contest in contests | filter:reportFilter">
<contestreport></contestreport>
</div>
Better way is to save the result of applying filter to the json data in a variable before ng-repeat reads items in the jsonArray like below.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-init="contests=
[{name:'bad apple', votingOver:false},
{name:'pleasurebuilder', votingOver:true},
{votingOver:true}]">
</div>
<div ng-init="reportFilter = {votingOver:true}">
</div>
<div ng-repeat="contest in revoluza = (contests | filter: reportFilter)">
{{contest}}
</div>
<hr>
</div>
Code 2 is not working because you have to create custom filter while you are only intializing div not creating filter
Code 1 is working because you are using proper syntax for default filter that can be compared with any object just like you did

Ng-repeat wont work

JS:
function ctrlr($scope, $http) {
$http.post(urlhere).success(function(data) {
$scope.Items = data;
});
}
HTML:
<body ng-app="">
<div ng-controller="ctrlr">
<div ng-repeat="item in Items">
{{ item.Name }}
</div>
</div>
</body>
Data returned from post request is a list of a class object (that contains Name property)
Checked, data is not empty.
It returns an xml formatted response.
Why won't my ng-repeat work? Tried using jquery ajax, which returned json but still no go
If you're running ng-repeat on a js object instead of array you should do something like this
<div ng-repeat="(key, val) in Items">
<span>{{key}}</span>
<span>{{val}}</span>
Well it may sound silly but the problem was that $scope.Items is being initialized in the success, an async method so it was undefined when it arrived to ng-repeat.
I solved it by switching to jquery ajax and adding async: false

How to reverse an array in angular js without creating a filter

I am having an array in controller as follows
function FooController($scope) {
$scope.items = ["a","b","c"];
}
I used ng-repeat to show the data in items,
<div ng-app>
<div ng-controller="FooController">
<ul ng-repeat="item in items">
<li>{{item}}</li>
</ul>
</div>
</div>
I got the result as a,b,c order. I want to show it in reverse order. that means c,b,a without changing its order in the controller or without creating a filter. How to do that?
Check this link
I faced the same problem, but with an array of objects. This quick solution worked for me, but using the filter is still the best practice.
<li data-ng-repeat="item in data.slice().reverse()">
...
</li>
http://bootply.com/SgVBZvZ708
In order to avoid the writting of a custom filter, I suggest you to use this syntax :
<ul ng-repeat="item in items | orderBy:'-toString()'">
The documentation assume you sort an array of Objects but in your case there are just plain strings.
Wrap the strings in objects and use orderBy or create a new filter:
angular.module("app",[])
.filter("reverse", function(){
return function(items){
return items.slice().reverse(); // Create a copy of the array and reverse the order of the items
};
});
And use it like this:
<ul ng-repeat="item in items|reverse">
Updated fiddle (I've also updated the ng-app directive so it's passed the "app" module.)

different elemens with ng-repeat

By AJAX I get JSON:
data : [
{
"type":"h2",
"PCDATA":"Title"
},
{
"type":"p",
"PCDATA":"First paragraph."
},
{
"type":"li",
"PCDATA":"list node"
},
{
"type":"p",
"PCDATA":"First paragraph."
}
]
and now I need to generate such HTML:
<h2>Title</h2>
<p>First paragraph.</p>
<ul>
<li>list node</li>
</ul>
<p>First paragraph.</p>
Can I do it using ng-repeat directive? How can I generate different HTML elements using one ng-repeat loop?
I don't think you can just use ng-repeat because I don't think something like <{{elem.type}}>{{elem.PCDATA}}</{{elem.type}}> inside ng-repeat would work.
Here's a fiddle for how to do it in controller: http://jsfiddle.net/terebentina/H3vQ9/3/
I simulated the ajax call with $timeout.
However, note that this is at the border of good practice - you shouldn't manipulate html inside your controller but in this case you could argue that you're manipulating data.
A better way to do it would be with a directive that would loop over your data, similar with how I did it in my example

Resources