Conditional open/close tag display - javascript

I'm wondering how to implement a task (which is very easy in server-side templating) in angular like:
{{ if condition }}
<div class="container">
{{ endif }}
<div class="child"></div>
{{ if condition }}
</div> <!-- closing container -->
{{ endif }}
I'm of course aware of ng-hide, ng-show and ng-hide... but it think I can't use these directives to implement my task... so what should I do?
ps: I can't do the following:
<div class="container" ng-if="condition">
<div class="child"></div>
</div>
<div class="child" ng-if="!condition"></div>
because I'm using the module operator (%) in order to wrap "child" nodes into "container" every X element (where X is a dynamic parameter)
the final result would be (supposing X is 4):
<div class="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
... and so on (I'm in a ng-repeat)

Group by filter in the template :
The key part of the solution is that we are computing a property containerId, which depends on the container size and on the index of the element in the array :
$scope.arrayItems.forEach(function(item, index) {
item.containerId = Math.floor(index / size);
});
Then in the template we group the elements by the property containerId :
<div class="container" ng-repeat="containers in arrayItems | groupBy: 'containerId'">
<div class="child" ng-repeat="item in containers">{{item.name}}</div>
</div>
That groupBy filter in the template comes from angular-filter
See fiddle
Group by in the controller:
In case you don't want to add angular-filter as a dependency, you could group the elements in the controller. The following example makes use of the groupBy function of lodash :
In the controller :
$scope.itemsGroupedByContainer = _.groupBy($scope.arrayItems, 'containerId');
In the template :
<div class="container" ng-repeat="containers in itemsGroupedByContainer">
<div class="child" ng-repeat="item in containers">{{item.name}}</div>
</div>
See fiddle

I think that you need the ng-repeat directive. Try something like this:
<div ng-repeat="item1 in repeat1 track by $index">
<div ng-repeat="item2 in repeat2 track by $index"></div>
</div>
Docs: https://docs.angularjs.org/api/ng/directive/ngRepeat
You don't need an if block to add a closing </div>

Related

Start and close element on condition in AngularJS ng-repeat

I've a HTML structure which looks like this :
<div class="row">
<div class="md-4">1</div>
<div class="md-4">2</div>
<div class="md-4">3</div>
</div>
<div class="row">
<div class="md-4">4</div>
<div class="md-4">5</div>
<div class="md-4">6</div>
</div>
<div class="row">
<div class="md-4">7</div>
<div class="md-4">8</div>
<div class="md-4">9</div>
</div>
and I've JS :
var abc = [1,2,3,4,5,6,7,8,9]
currently as per my structure I can't directly run ng-repeat as after every 3 records I want starts and ends
I want something similar like
<div ng-repeat="val in abc" class="row" ng-if="$index%3==0">
<div>{{val}}</div>
</div>
but above codes don't work and I know its incorrect way but I want something similar to that
please try with this code:
<div ng-repeat="val in abc track by $index" class="row" ng-if="$index%3==0">
<div>{{val}}</div>
</div>
If you've used lodash before
var arr = _.chunk(abc,3);
//makes your array like [[1,2,3],[4,5,6],[7,8,9]]
<div ng-repeat = "a in arr" class = "row">
<div ng-repeat="b in a" class="md-4">{{b}}</div>
</div>
you can lookup lodash here

Removing div's and keep content

I'm trying to remove the following DIV's:
<div class="whatever_name">
<div class="whatever_name">
<h2>subtitle</h2>
<p>content<p>
</div>
</div>
and need the following output:
<h2>subtitle</h2>
<p>content<p>
Using jQuery, I can not use remove() because it clear the content too. With pure javascript, happens the same.
I have no idea how to accomplish this issue.
Any idea?
EDIT:
Not always the structure is the same. It can vary, i.e.:
<div class="whatever_name">
<div class="whatever_name">
<div class="whatever_name">
<h2>subtitle</h2>
<p>content<p>
</div>
</div>
</div>
Just need an iterator that can handle such task.
Use unwrap() method twice on the children element.
$('.content .post-12')
// get children elements, or use contents()
.children()
// use unwrap twice to unwrap two parents
.unwrap().unwrap()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="post-12">
<h2>subtitle</h2>
<p>content</p>
</div>
</div>
UPDATE : With the updated content you just need to change the selector with your requirement.
$('div > div > h2,div > div > p').unwrap().unwrap()
// or use
// $('div > div:has(h2):has(p) > *')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="whatever_name">
<div class="whatever_name">
<div class="whatever_name">
<h2>subtitle</h2>
<p>content
<p>
</div>
</div>
</div>

AngularJS ng-repeat with seperator every two items

The layout I'm trying to achieve is this:
<div>
<div class="row">
<div></div>
<div></div>
</div>
<div class="row">
<div></div>
<div></div>
</div>
<div class="row">
<div></div>
<div></div>
</div>
</div>
Doing this gets me the divs, but how can I add separators between every two items? I feel like Angular should have an easy way to do this.
<div>
<div class="row">
<div ng-repeat="object in objects"></div>
</div>
</div>
I think, you can solve it using a bit of javascript and ng-repeat like
<div>
<div class="row" ng-repeat="array in obj2">
<div ng-repeat="object in array">{{object}}</div>
</div>
</div>
then in your angular controller create a new object called obj2 using the objects array like
$scope.obj2 = [];
while ($scope.objects.length) {
$scope.obj2.push($scope.objects.splice(0, 2))
}
Demo: Fiddle
If i get what you want to do, you could use the $index property of rgRepeat and then use modulo for that index like:
<div ng-repeat="object in objects">
<div>My Content</div>
<div data-ng-show="$index % 3 == 0">My Seperator</div>
</div>

AngularJs ng-repeat does not update after filter object gets updated

Hi I am working on requirement where my filter object is keep getting changed and because of that i have to change ng-repeat on div.
html code :
<div class="col-md-6" ng-repeat="model in models | filter:{ModelText : '!All models', ModelId: '!FilteredModelIds'}:true">
<div class="well">
<div class="media">
<div class="media-object small"><i class="pp-car"></i></div>
<div class="media-body">
<div class="text-box">
<h3>{{model.ModelText}}</h3><span class="hr-small"></span>
</div>
<div class="dashboard-control clearfix">
<div class="simple-metric text-left sub-metric">
<div class="metric-title">Satisfaction score</div>
<div class="metric-number text-red">{{model.SatisfactionAvg}}</div>
</div>
<div class="simple-metric text-left sub-metric">
<div class="metric-title">Total interviews</div>
<div class="metric-number">{{model.TotalInterviews}}</div>
</div>
</div>
<ul class="list-standard">
<li> View interviews</li>
</ul>
</div>
</div>
</div>
</div>
here is the angular js code:
function getModelId() {
dataFactory.getModelIdByFilter($scope.region, $scope.subregion).success($scope.handleSuccess).then(function (result) {
$scope.FilteredModelIds = result.data;
});
}
Model json :
[{"ModelId":0,"ModelText":"All models","Sequence":0,"TotalInterviews":0,"SatisfactionAvg":0.000000},{"ModelId":1,"ModelText":"A3","Sequence":20,"TotalInterviews":2062,"SatisfactionAvg":9.637245},{"ModelId":2,"ModelText":"A4","Sequence":30,"TotalInterviews":3106,"SatisfactionAvg":9.743721},{"ModelId":3,"ModelText":"A5","Sequence":40,"TotalInterviews":1863,"SatisfactionAvg":9.694041},{"ModelId":4,"ModelText":"A6","Sequence":50,"TotalInterviews":280,"SatisfactionAvg":9.642857},{"ModelId":5,"ModelText":"A8","Sequence":70,"TotalInterviews":46,"SatisfactionAvg":11.217391},{"ModelId":9,"ModelText":"Q5","Sequence":110,"TotalInterviews":3176,"SatisfactionAvg":9.503778},{"ModelId":10,"ModelText":"Q7","Sequence":120,"TotalInterviews":1355,"SatisfactionAvg":9.685608},{"ModelId":11,"ModelText":"R8","Sequence":130,"TotalInterviews":31,"SatisfactionAvg":10.064516},{"ModelId":12,"ModelText":"TT","Sequence":140,"TotalInterviews":408,"SatisfactionAvg":9.764705},{"ModelId":13,"ModelText":"A1","Sequence":10,"TotalInterviews":1087,"SatisfactionAvg":10.097516},{"ModelId":14,"ModelText":"A7","Sequence":60,"TotalInterviews":263,"SatisfactionAvg":10.190114},{"ModelId":15,"ModelText":"Q3","Sequence":105,"TotalInterviews":1045,"SatisfactionAvg":9.542583}]
on page load its showing proper data with filter. but on change of filtered object in my case FilteredModelIds, its not getting updated. any help is appreciated.
please let me know if i am worng here.
Thanks.

Write a jQuery selector to filter the child divs having no subclasses

Consider the following HTML
<div class="container">
<div class="item medium type"> value1 </div>
<div class="item"> value2 </div>
<div class="item large"> value3 </div>
<div class="item small"> value4 </div>
<div class="item"> value5 </div>
<div class="item"> value6 </div>
<div class="item"> value7 </div>
<div class="item medium"> value8 </div>
<div class="item"> value9 </div>
</div>
Is there a straightforward way to write a jQuery selector to get all the children of the container div which does not possess any subclasses ?
For example, I need to write a selector ($('myselector').each()) and get only the item divs with values value2,value5,value6,value7,value9 (as these divs don't have any subclasses).
May be I am missing the obvious. But I did a quick search to get little information on this.
You can use this selector:
$('.container [class=item]')
It get every child with a class attribute exactly equal to item (so there is no other class).
But it's not really scalable, what if you need to add another class that don't exclude the element?
Maybe you should consider adding a class to other elements like:
<div class="container">
<div class="item sub medium type"> value1 </div>
<div class="item"> value2 </div>
<div class="item sub large"> value3 </div>
<div class="item sub small"> value4 </div>
<div class="item"> value5 </div>
<div class="item"> value6 </div>
<div class="item"> value7 </div>
<div class="item sub medium"> value8 </div>
<div class="item"> value9 </div>
</div>
And then use :not in your selector:
$('.container .item:not(.sub)')
You can use $("div[class$='item']")
Also you may take a look at http://api.jquery.com/category/selectors/
If you use the attribute selector like this:
$('.container [class=item]')
then it will only match an element that is exactly like this:
<div class="item">value1</div>
and not this (notice the whitespace around the class name "item"):
<div class=" item ">value1</div>
It is not safe to assume that there will never be whitespace in the class attribute. It's possible that whitespace gets inserted or left behind as the result of some jQuery DOM manipulation. A solution to this would be to trim the class attribute before selecting all elements with only the class "item".
$('.container')
.children() // select all the elements contained within .container
.each(function(){
// strip whitespace from class attribute
$(this).attr('class',$.trim($(this).attr('class')));
});
// fade out all elements within .container that ONLY have the class
// "item" and nothing else
$('.container [class="item"]').fadeOut();
try not
$('.container .item').not('.medium , .large,.small,.type')
or the attribute selector
$('.container [class=item]').each(function(){
//do your stuff
});

Categories

Resources