Create html elements in ngRepeat depending on object properties - javascript

I have an array of objects that have two fileds for example :
var array = [{type:"range", group:"group1"}, {type:"boolean", group:"group1"},
{type:"input", group:"group3"}... ]
Now in HTML by iterating through the array I want to create a div for every different GROUP and put the all elements with that group inside. But by putting I mean creating Inputs or Radiobuttons or Dropdowns depending on the TYPE of the element.
Now I have done this using AngularJS and mostly JS by appending objects to existing ones and so on. But I want to reduce as much as possible the usage of js because I am having issue with calling a function after the HTML is loaded (Call function after HTML is loaded AngularJS).
So I will be thankfull if someone give me an advice how this should look like mostly in html. I imagine something like this :
<div ng-repeat="object in array track by $index">
//if object.group div exists add to existing one (check maybe with js function ?)
// if object.type is ... add ...
// else if objec.type is ... add ...
...
//else object.group not exists create div with id object.group for example
// if object.type is ... add ...
// else if object.type is ... add ...
...

This should work for your case:
<div ng-repeat="(key, value) in array | groupBy: 'group'">
Group: {{key}}
<div ng-repeat="object in value">
<div ng-switch on="object.type">
<div ng-switch-when="range">Range block</div>
<div ng-switch-when="boolean">Boolean block</div>
<div ng-switch-when="input">Input block</div>
</div>
</div>
<br>
</div>
First looping groups elements, second will work with an elements in a group

Related

How to check if text exist inside class using Selenium and JavaScript

I'm new to Selenium. I like to verify if a specific class contains a text snippet in JavaScript.
I have following HTML:
<div class="product-small">
<div class="data">
<p>This is some Text</p>
</div>
</div>
<div class="product-small">
<div class="data">
<p>This is some Text</p>
</div>
</div>
...
The above class are available multiple times on the page, so i have to iterate the "product-small" class to check if all 12 classes contains the text "some". If one of the 12 elements with that "product-small" class does not contain the text "some", the test will fail.
I thought something like this:
const cars = driver.findElements(By.className('product-small'));
cars.forEach(function (element) {
// Check if element contains "some" inside class "data"
// If element does not contain "some", test will fail
});
Thank you :)
A generic solution would be to collect the elements using the following xpath based Locator Strategy and probe the length, if it equals to 12 then mark it as Pass else mark it as Fail
const cars = driver.findElements(By.xpath("div[#class='product-small']//p[contains(., 'some')]"));

How inject data after every certain count in angularjs

I have some SQL data which I am fetching from the database, I am using angular js with an ng-repeat directive to list all rows below is my code:
<div class="wrapper">
<div class="content" ng-repeat="row in rows">
{{row.someData}}
</div>
</div>
Now I have some custom advertisement banners which I want to show after every 4th row but I don't know how to it with angular Js so please help me here
Apart from Panos K's way what you can do is have one flag to check if banner data is received from web service and then add it after every 4th row of data already loaded. So, for that have ng-if condition inside ng-repeat & then bind that new bannerData arry/objects with index as $index/4.
Check below Plunker example I've created to demonstrate this. Click on Banner data button to make async call to get banner data & then binding it to existing data loaded using ng-repeat
<div ng-repeat="x in records track by $index">
<div class="column">{{x.name}}</div>
<div class="column">{{x.abbreviation}}</div>
<div ng-if="isBannerDataAvailable && ($index+1) % 4 === 0" class="banner">
<p>Banner After every 4th row</p>
<p> {{showBannerData($index)}} </p>
</div>
</div>
Where showBannerData() can be:
$scope.showBannerData = function($index) {
var index = $scope.Math.round(($index + 1) / 4) - 1;
return $scope.bannerData[index].Banner;
}
Working plunker Example
First edit your question with your last comment.
what you need to do is add banners to your model ($scope.rows in your case)
So when you fetch your banners (onSuccess) do this
banners.forEach((element,index)=>{
if(index%4==0)
$scope.rows.splice(index,0,element);
})

Avoiding a large amount of hidden elements for in place editing with angularjs

I have a rather large list with todo items for which I want to add in place editing for:
[ ] first todo
[ ] second todo
[ ] third todo
after clicking on the second todo, the text of the second todo can be edited but you can also set some properties on the todo:
[ ] first todo
-----------------------------------------------------------
| [ ] second todo__________________ |
| due: __/__/____ |
| assigned: ______________ |
| |
| [save] [cancel] |
-----------------------------------------------------------
[ ] third todo
Now I can do something like:
<div ng-repeat="todo in todos">
<div ng-show="!doedit">
<input type="checkbox"> {{todo.title}}
</div>
<div ng-show="doedit" class="boxed">
<input type="checkbox"><input type="text" ng-model="todo.title"><br>
<input type="date" ng-model="todo.due"><br>
<input type="text" ng-model="todo.assigned"><br>
<button ng-click="doedit = false">save</button>
</div>
</div>
This should work (ignoring how the cancel button should work) but if I have a large todo list (100+ items) it will create a large amount of hidden elements which are probably never used but still bound to variables.
Is there a better way to do this? I looked at angular-xeditable which seems to dynamically add elements but it only works for simple input elements.
Or is having a large amount of hidden elements not an issue in angular?
ng-if removes the element from DOM entirely if it evaluates to false, including any watchers. For example:
<div ng-if="doEdit"></div>
This post explains some of the differences between ng-if and ng-show.
Having large amounts of hidden elements is not an issue only with the js but also with the DOM itself. you should not be doing that.
What can be done instead is
1. Using ng-if - keep a state of all the element lets say isEdited after the user clicks on the todo. Set the variable / state isEdited = !isEdited. This would set it to true if it is not already. Then inside your DOM write HTML using ng-if. Something like this
<div class="to-do-item"></div><br>
<div ng-if="isEdited">
<!--UI for the edited part-->
</div>
Since ng-if does not render the html till the condition is true. There wont be too much load on the DOM.
2. If the template for editing the to do item is same for all the todo items. You should prefer using ng-include with ng-if. This way the template would be downloaded the first time you try to edit the element. Then you can cache it so not network lag. Also there is no extra hidden html. Whatever needs to be on the page is on the page and is not hidden.
Wrapping all of that editing section into one container with an ng-if would reduce the number of internal watches down to one for the whole section when it wasn't active

Jquery find and append performance issue when building big hierarchy

I need to recursively read a hierarchic JSON object and build the HTML the same way as children objects will have to be inserted inside parents object.
Example:
<div class="level0">
<div class="children1 level1">
<div class="children1 level2">
.... N children
</div>
... N Children
</div>
</div>
... N Parents
Now, I'm building this with the following code:
function buildDivHtml(); // This generates all the parent/children code at that particular moment, meaning one by one.
object.find('selector of the row where the append goes').append('html from above function');
This causes browser to freeze. Is there a way to do this that works flawlessly without browser freezing?

Angularjs appending templates to each other

how to append code to already existing <div ng-view> container.
like I have template with the following code:
<p>{{date}}</p>
<div ng-repeat='i in items'>
<span>{{i.created}}</span>
<span>{{i.order}}</span>
<span>{{i.customer}}</span>
</div>
then by ajax we loading next date items and so on..so how to make the templates to append in the end, not replace each other and look like:
2013-05-03
created
order
customer
created
order
customer
created
order
customer
2013-05-04
created
order
customer
2013-05-05
created
order
customer
created
order
customer
and so on..
?
thank you in advance.
You need to create a parent ng-repeat as follows:
<div ng-repeat="entry in invoices">
<p>{{entry.date}}</p>
<div ng-repeat='i in entry.items'>
<span>{{i.created}}</span>
<span>{{i.order}}</span>
<span>{{i.customer}}</span>
</div>
</div>
Thus, when your server is loading the next date items, simply add the same to invoices array.

Categories