Filters in Angular Js - javascript

I am trying to apply the filters on the ng-repeat based on user selection in section options.But unable to do that so far.
Update-It works !!
Here's Plunker
HTML
<div class="container">
<div ng-include="" src="'refiners.html'"></div>
<br />
<br />
<div class="row">
<div class="col-xs-12">
<ul>
<li ng-repeat="item in data.Results | filter:cc">
<div>
<p>{{item.Title}}</p>
<p>{{item.City}}</p>
<p>{{item.PostalCode}}</p>
<span>{{item.MinimumSalePrice | currency}}</span>
<span>{{item.MaximumSalePrice |currency}}</span>
<p>{{item.PropertyType}}</p>
<p>{{item.TenureType}}</p>
</div>
</li>
</ul>
</div>

When you do ng-include you create a new scope so cc is always empty in the parent scope.
This is similar to the issue in this in question. AngularJS - losing scope when using ng-include
You can fix it by adding $scope.cc={} to your controller (creating this element in the parent $scope so the filter has access to it. For this to work you will have to remove the ng-init calls from refiners.html, since these will create a new object in the child scope.

Related

$index issue in Angular

I am having issue with $index in angular.I have a ng-repeat inside which I am using $index to keep track of unique class.
Here is my code:
<div ng-repeat="style in styleArr">
<div class="myclass{{ $index }}">
</div>
</div>
In angular controller I am appending a div inside myclass0,But not working.
Here is my controller.
myClass = angular.element('.myclass0');
myClass.append('<div class="test">Hello World..<test>');
When I try to do this:
<div ng-repeat="style in styleArr">
<div class="myclass0">
</div>
</div>
Its working fine.Any suggestion?
I think you want a unique classes for each div for applying a unique CSS. You can implement it by assigning a unique class or assigning a unique Id. For a Class, you need to use "ng-class" directive.
<div ng-repeat="style in styleArr">
<div ng-class="myclass{{ $index }}">
</div>
</div>
For a unique Id use :
<div ng-repeat="style in styleArr">
<div id="style{{ $index }}">
</div>
</div>
Best option is to use unique Id for performing a operation. If you want to assign only a styles then use Unique classes.
Use ng-class, it allows for expressions in the class name
<div ng-repeat="style in styleArr">
<div ng-class="myclass{{ $index }}">
</div>
</div>
More info on ng-class: https://docs.angularjs.org/api/ng/directive/ngClass
Use "ng-class" instead of "class"
<div ng-repeat="style in styleArr">
<div ng-class="myclass{{ $index }}">
</div>
</div>
you have to change class for ng-class
You can't do it reliably the what you are trying to do it. You need to understand how digest cycle and compilation/rendering of templates in Angular works. Then you would understand that element with class myclass0, myclass1, etc. - are not available at the time yo are trying to fetch them from DOM. Again - this is the reason why you should never do any DOM manipulations in controllers.
You should either use custom directive i your case or existing Angular directives like ngIf/ngShow, etc.
For example:
<div ng-repeat="style in styleArr">
<div class="myclass" ng-if="style.show">
<div>Hello ...</div>
</div>
</div>
and in controller
// show "Hello" in the first myclass
$scope.styles[0].show = true;
My advice would be not to have DOM manipulation inside controllers. That is what directive is used for. However in your case if you just want to append a div for the first iteration you can do something like this:
<div ng-repeat="style in styleArr">
<div ng-show="$first" class="test">Hello World..</div>
</div>
More on ng-repeat and $first

How to set scope variable inside ng-repeat?

I want to determine whether any ng-repeated element is rendered.
I write this code
<div ng-show="anyRendered">Any has been rendered</div>
<div ng-show="anyFilterActive">ANY FILTER IS ACTIVE</div>
<div class="selected-filter-value" ng-if="filter.name && filterCtrl.isActiveFilter(filter)" data-ng-repeat="(name, filter) in filterOptions">
<span ng-init="anyFilterActive = true;">{{filter.name}}:</span>
</div>
But this code doesn't work. Also I try to write $parent.anyRendered inside ng-repeat.
Try with ng-if
<div ng-show="filterOptions.length > 0">Any has been rendered</div>
<div ng-if="filterOptions.length > 0" ng-repeat="(name, filter) in filterOptions">
<span></span>
</div>
just use $index
<div ng-repeat="(name, filter) in filterOptions">
<span ng-show="$index > 0"></span>
</div>
ngRepeat Docs $index
In the example in the ng-repeat docs u can see the usage of $index
You must not write code logic in your templates: all the code must be in your controllers, filters, directives and services. The ng-init directive is only here so that you can create aliases to make your templates simpler.
Filters and directives contain "presentation code" and controllers and services contain "business related code".
You could create a filter to know if an object is empty or not (filter code from another question), and use it with ng-if, ng-show...
Resulting template:
<div ng-if="filterOptions|empty">
Nothing to show!
</div>
<div ng-repeat="(k, v) in filterOptions">
{{k}}, {{v}}
</div>

Updating the limitTo value on a specific nested ngRepeat

I'm new to AngularJS and having to work on an app that has a section of nested ngRepeats such as this below.
<div class="title-bar" ng-repeat="orderType in someObj.orderTypes">
<div class="inner-panel" ng-repeat="status in orderType.statuses">
<p>{{status.Name}}</p>
<div class="order-list" ng-repeat="order in status.Orders | limitTo:orderFilterLimit">
<p>{{order.Stuff}}</p>
</div>
<button ng-show="(status.Orders.length > orderFilterLimit)" ng-click="loadMoreOrdersToList()">Load More</button>
</div>
</div>
The status.Orders list can be quite large at times so I limit it. When a user wants to view more data for that specific section (which is enumerated by status) I add 3 to the orderFilterLimit. The problem is when I do this it is adding 3 to every single .order-list in the .inner-pannel element. Is there a way I can change the orderFilerLimit variable based on an id or class of the element it's attached to?
For context here is a super simple snippet of what loadMoreOrdersToList() is doing.
https://jsbin.com/vapucixesa/1/edit?js
No need of declare the orderFilterLimit inside controller, You should have scope variable inside ng-repeat itself so that it ng-repeat element will have separate copy of orderFilterLimit because ng-repeat create a child scope on each iteration.
Markup
<div class="title-bar" ng-repeat="orderType in someObj.orderTypes" ng-init="orderFilterLimit = 3">
<div class="inner-panel" ng-repeat="status in orderType.statuses">
<p>{{status.Name}}</p>
<div class="order-list" ng-repeat="order in status.Orders | limitTo:orderFilterLimit">
<p>{{order.Stuff}}</p>
</div>
<button ng-show="(status.Orders.length > orderFilterLimit)" ng-click="orderFilterLimit = orderFilterLimit + 3">Load More</button>
</div>
</div>

Passing models in AngularJS

I am building my first AngularJS app comming from backbone. I have a list where the user can select an item. The goal is show the details of the selected item in a view below the list. The list-view and detail-view are both part of the main-view.
my list view
<div id="rfc-records" class="container-fluid">
<div ng-repeat="record in records" ng-click="selectRow()" class="row select table-row">
<div class="col-lg-1 center">
{{record.id}}
</div>
<div class="col-lg-1 center">
{{record.rfcObject}}
</div>
<div class="col-lg-5">
{{record.rfcFunction}}
</div>
<div class="col-lg-2">
{{record.status}}
</div>
<div class="col-lg-3">
{{mii.utils.date.extToIntDate(record.firstProcessing)}}
</div>
</div>
</div>
As you see I already added an event to each row: ng-click="selectRow()".
It is unclear to me how to know the selected row in this function. I could do something like this :
ng-click="selectRow(record)
MainController
$scope.selectRow = function(record){
alert(record.id); // undefined
}
The result is undefined so this does not work. Plus this seems like a bad approach to pass the model back from the view to the controller. I might be able to get the application working but I have the feeling that I won't be using the paradigm as intended.
In backbone I would have a seperate view for each row where the model is bound to. But in Angular models aren't as explicit as in backbone.
In general I don't really understand how models work in Angular. R
Regarding this example I have the following questions:
How do I know what item is selected in the list
Where should I put the selectRow function? In the controller of the Mainview or in the list-view directive?
How do I pass the selected model to the details-view.
Well, passing current item into ngClick handler is pretty usual way to solve this task. I'm not sure why it's not working for you, it should. Here is the example of this typical approach.
In backbone I would have a seperate view for each row where the model is bound to. But in Angular models aren't as explicit as in backbone.
Actually Angular is even more elegant in this concern. You still have model available in every iterated row. You can refer current child scope as this in controller. So in your case if you don't want to pass record object into controller function on click, you can use this and it will point to the current scope object (remember that ngRepeat creates new child scope for every row):
$scope.selectRow = function() {
alert(this.record.id);
};
and you don't have to pass anything in HTML:
ng-click="selectRow()"
Demo: http://plnkr.co/edit/kN0vB6N6v7XnqASRSmAd?p=preview
ng-click and ng-repeat are in same div. You can add a new div in this repeated div like and this is works for me :
<div id="rfc-records" class="container-fluid">
<div ng-repeat="record in records" class="row select table-row">
<div class="col-lg-1 center">
Select This item<input type=button ng-click="selectRow(record)">
</div>
<div class="col-lg-1 center">
{{record.id}}
</div>
<div class="col-lg-1 center">
{{record.rfcObject}}
</div>
<div class="col-lg-5">
{{record.rfcFunction}}
</div>
<div class="col-lg-2">
{{record.status}}
</div>
<div class="col-lg-3">
{{mii.utils.date.extToIntDate(record.firstProcessing)}}
</div>
</div>
</div>

How to use a controller outside of ngApp's scope

Due to the structure of an existing project I'm working on, I'm stuck with a template that looks like this:
<div ng-app="example">
<div ng-controller="MainCtrl" id="inner">
{{ inside }}
</div>
</div>
<div ng-controller="MainCtrl" id="outer">
{{ outside }}
</div>
#outer is supposed to be using the same controller as #inner, but as it's located outside of ngApp's scope, {{ outside }} will not be evaluated. Unfortunately I can't change the template structure, so I tried to compile #outer's content like this:
app.run(function($rootScope, $compile){
$rootScope.$apply($compile(document.getElementById('outer'))($rootScope));
});
This works, but the controller function will be executed twice, which is not desired. Is there a better way to achieve my goal?
Working example on Plunker
what you could do instead, is NOT define ng-app at all in the html, and instead bootstrap angular via javascript.
for example you can do angular.bootstrap(document, ['example']); where 'example' is the angular module for the app for example angular.module('example', [
'ngResource', 'ui.router', ....
]);
you probably defined that yourself already.
This way, you define the ng-app on the entire document scope.
That is normal, you're initializing twice the controller. You could simply create another div, wrapping all the divs you want and use alias. But this will still initialize twice, but each div will have different values, like, {{inside}} on first div will not have the same as the second one has.
<div ng-app="example">
<div>
<div ng-controller="MainCtrl as FirstCtrl" id="inner"> // alias FirstCtrl
{{ inside }}
</div>
</div>
<div ng-controller="MainCtrl as SecondCtrl" id="outer"> // alias SecondCtrl
{{ outside }}
</div>
</div>
But if you intend to use just once the same controller, as far as I'm concerned, you'll have to wrap all divs you want to use the same controller, in just one div, like:
<div ng-app="example" ng-controller="MainCtrl">
<div id="inner">
{{inside}}
</div>
<div id="outer">
{{outside}}
</div>
</div>
This will initialize just once.
Other way, could be attaching ng-app and ng-controller in your html/body tags.

Categories

Resources