How to select an element from _ngcontent block using protractor? - javascript

I have below structure for my angular app.
<div _ngcontent-c8 class=“page-body”>
<div _ngcontent-c8 class=“cell-list”>
<a _ngcontent-c8="" class="cell cell-row ng-star-inserted"
queryparamshandling="preserve" ng-reflect-query- params-
handling="preserve" ng-reflect-router-link=“/path” href=“/link”
</a>
<a _ngcontent-c8="" class="cell cell-row ng-star-inserted"
queryparamshandling="preserve" ng-reflect-query- params-
handling="preserve" ng-reflect-router-link=“/path” href=“/link”
</a>
<a _ngcontent-c8="" class="cell cell-row ng-star-inserted"
queryparamshandling="preserve" ng-reflect-query- params-
handling="preserve" ng-reflect-router-link=“/path” href=“/link”
</a>
</div>
How would I select specific a tag from this structure? In the previous version of angular with ng-repeat directive, I could use "(element.all(by.repeater))".However it does not work for the above code.
I tried using element.all(by.css)), but that does not work either.
Do you guys have any suggestions?

Try following code:
getByAttribute(searchText: string): ElementFinder {
let container = element(by.css('.page-body .cell-list'));
return container.all(by.tagName('a')).filter(function(el) {
return el.getAttribute('href').then(function(value) {
return value.trim() === searchText;
});
}).first();
}
This code lists all a elements and filters them by it's href value. This is an example for showing you how to filter values.

Related

Change bootstrap color class every loop in Laravel (blade)

I have a limited data list (only displaying the top 5). I'd look like this :
And the problem is how to make the icon in different color using Bootstrap class. I want the icon in that list have 5 color like bg-light-primary for the first, bg-light-danger for the second, bg-light-success for the third, etc. The way I display the data is using Laravel #foreach. Like this:
#foreach ($diklats->where('status', 'Active')->take(5) as $diklat_list)
<div class="transaction-item">
<a href="javascript:void(0)" class="text-dark">
<div class="media">
<div class="avatar bg-light-primary rounded">
<div class="avatar-content">
<i data-feather="book" class="avatar-icon font-medium-3"></i>
</div>
</div>
<div class="media-body ml-1">
<h6 class="transaction-title">{{$diklat_list->name}}</h6>
<small>{{$diklat_list->userDiklat->where('is_approve',1)->count()}} </small>
</div>
</div>
</a>
<div class="font-weight-bolder text-danger"></div>
</div>
#endforeach
In this is the controller:
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\{Diklat, User, UserDiklat, Regency};
use Illuminate\Support\Facades\DB;
class DashboardController extends Controller
{
public function index()
{
$diklat = Diklat::where('status', 'Active')->count();
$participant = User::where('is_participant', 1)->count();
$regency = Regency::all()->count();
$diklats = Diklat::with('userDiklat')->get();
return view('admin.index', compact('diklats', 'diklat', 'participant', 'regency'));
}
}
I have search for this case but still didn't get it and
I'm in the learning stage. Would you help me, please? Thank you in advance.
Solved with this:
#php ($icons = ["bg-light-primary","bg-light-success","bg-light-danger","bg-light-warning", "bg-light-info"])
<div class="avatar {{$icons[$loop->index]}} rounded">
<div class="avatar-content">
<i data-feather="book" class="avatar-icon font-medium-3"></i>
</div>
</div>
Create an array of your values and use a random value from that array to use that as a class.
<?php $class_array = array("bg-primary","bg-danger","bg-success","bg-warning"); ?>
<div class="avatar-content">
<i data-feather="book" class="avatar-icon font-medium-3 {{$class_array[array_rand($class_array)]}}"></i>
</div>
It is recommended that you should not use random class as it might repeat or all of them could be same at a time.

I need to change html class attribute for every ng-repeat element with button

i have html div where i use ng-repeat that gives me back elements from array
<div>
<div class="col-sm-3" ng-repeat="el in vm.filmovi " id="filmovi">
<img src="http://image.tmdb.org/t/p/w500/{{el.poster_path}}" style="width:100%;"><br>
<a ng-click="vm.set_favorit(el)" style="cursor:hand; color:white;" uib-tooltip="Postavi u omiljene">
<i class="glyphicon" ng-class="{'glyphicon-star-empty':el.favorit!=true, 'glyphicon-star':el.favorit==true}"
aria-hidden="true"></i></a>
<a href="http://www.imdb.com/title/{{el.imdb_id}}/" style="color:white;">
<strong>{{ el.title | limitTo: 20 }}{{el.title.length > 20 ? '...' : ''}}</strong></a>
<a class="glyphicon glyphicon-share-alt" style="margin-left:5px; color:white;" ng-click="vm.open()" uib-tooltip="share" ></a><br>
{{el.popularity}} <br>
<a style="color:white;" href="#" ng-click="vm.filter(genre)" ng-repeat="genre in el.genres"><small>{{genre.name}} </small></a>
<div ng-init="x = 0">
<span uib-rating ng-model="x" max="5"
state-on="'glyphicon-star'"
state-off="'glyphicon-star-empty'"></span></div>
</div>
</div>
now i created a button that changes value of id "filmovi"
<li><a href="#" ng-hide="vm.ulogovan" ng-click="vm.dugme();" >losta</a></li>
and created function vm.dugme() that gets element by id and sets class atribute to col-sm-4
vm.dugme=function(){
document.getElementById("filmovi").setAttribute("class","col-sm-4");
};
but when i did that only the first element changed
but i need for all of them to change to col-sm-4 , any suggestion?
Don't do DOM manipulation from angularjs controller. Instead make use of directive provided by angular.
You could use ng-class with expression so that whenever expression gets satiesfied the class will be added over that DOM. To add class put addColSm4 flag inside a controller and change that flag from dugme method of your controller. Also by looking at screenshot it seems like you need col-sm-3 class at the beginning, afterwards you need to apply col-sm-4.
HTML
<div class="row">
<div class="col-sm-3" ng-repeat="el in vm.filmovi"
ng-class="{'col-sm-4': vm.addColSm4, 'col-sm-3': !vm.addColSm4 }" >
.. Html will stay as is ..
</div>
</div>
<li>
<a href="#" ng-hide="vm.ulogovan"
ng-click="vm.dugme()">
losta
</a>
</li>
Code
vm.dugme = function (){
vm.addColSm4 = true;
};
Demo Plunker

Angular active ng-class isn't working properly

I have some angular code that is supposed to assign a class to only the parent element of the link clicked. This seems to work initially, but then after clicking around a bit, the code seems to get stuck. Here is some sample code of what I'm working with:
<div ng-repeat="item in items track by item.id" class="row" ng-class="{'active': selectItem.this == item.id}">
<a ng-click="selectItem.this = item.id">Move to top</a> {{item.name}}
$scope.selectItem = { this: -1 };
http://plnkr.co/edit/jhahff7OyVTVt615BBp3?p=preview
Any help would be great!
You just need to make the whole text a clickable DOM
<div ng-repeat="item in items track by item.id" class="row" ng-class="{'active': selectItem.this == item.id}">
<a ng-click="selectItem.this = item.id">Move to top <span ng-bind="item.name"></span></a>
</div>
I replaced the a tag with p tag and bind an click event to the p tag. With this refactoring, I don't see any lagging or weird behaviour.
<body ng-controller="MainCtrl">
<div ng-repeat="item in items track by item.id" class="row"
ng-class="{'active': selectItem.this == item.id}">
<p style="cursor: pointer;" ng-click=selectedItem()>
Move to top {{item.name}}
</p>
</div>
</body>
In controller
$scope.selectItem = {};
$scope.selectedItem = function () {
$scope.selectItem.this = this.item.id;
};
Let me know if you still see any issues.

ng-switch is not matching with the expected option

I'm having problems with angularjs ng-switch
JS
function TestCtrl($scope) {
$scope.currentUser = {"userId":"1","userRole":"N"};
$scope.userRoles = {"normal":"N","admin":"A"}
$scope.patient = {name: 'John'};
}
HTML
<div ng-switch on="currentUser.userRole">
<a ng-switch-when="userRoles.normal" href="normalUrl">
{{patient.name}}
</a>
<a ng-switch-when="userRoles.admin" href="adminUrl">
{{patient.name}}
</a>
<div ng-switch-default> default </div>
</div>
</div>
I expect the name of the patient to be displayed with a link to normalUrl but 'default' is displayed. What am I doing wrong?
Here is a fiddle with the code
The ngSwitchWhen directive does not evaluate expressions (although I've heard this might be added to 1.3). The value is interpolated as a string literal, so you would have to use it like this:
<a ng-switch-when="N" href="normalUrl">
That will work, but if you really need to dynamically determine your when value, then maybe ngIf will better suit your needs:
<a ng-if="currentUser.userRole === userRoles.normal" href="normalUrl">
<a ng-if="currentUser.userRole === userRoles.admin" href="adminUrl">

AngularJS ngRepeat element removal

There are quite a few questions on how to implement item removal inside ngRepeat directive, and as I figured out, it comes down to using ngClick and triggering some remove function passing it item's $index.
However, I couldn't find anywhere an example where I have multiple ngRepeats:
<div ng-controller="MyController">
<div ng-repeat="email in user.emails">
{{ email }} <a href>Remove</a>
</div>
<div ng-repeat="phone in user.phones">
{{ phone }} <a href>Remove</a>
</div>
</div>
For this, I would need to create $scope.removePhone and $scope.removeEmail which would be called using ngClick on Remove anchor. But I'm looking for a more generic solution. Especially since I have many pages with many ngRepeats .
I was thinking about writing a directive which would be placed on Remove anchor and would do something like this:
Find ngRepeat among parent elements.
Read what it's iterating over ('user.emails' in first case, 'user.phones' in second)
Remove $index element from THAT model.
So the markup would look something like this:
<div ng-controller="MyController">
<div ng-repeat="email in user.emails">
{{ email }} <a href remove-directive="$index">Remove</a>
</div>
<div ng-repeat="phone in user.phones">
{{ phone }} <a href remove-directive="$index">Remove</a>
</div>
</div>
Is what I'm looking for possible to achieve and what would be the preferred way to do this?
Current hacky solution
Here is how I do it currently. It's hacky and ugly but gets the job done until I figure out a prettier way.
myAppModule.controller('MyController', function ($scope, $parse, $routeParams, User) {
$scope.user = User.get({id: $routeParams.id});
$scope.remove = function ($index, $event) {
// TODO: Find a way to make a directive that does this. This is ugly. And probably very wrong.
var repeatExpr = $($event.currentTarget).closest('[ng-repeat]').attr('ng-repeat');
var modelPath = $parse(repeatExpr.split('in')[1].replace(/^\s+|\s+$/g, ''));
$scope.$eval(modelPath).splice($index, 1);
};
});
And in DOM:
<div ng-repeat="email in user.email" class="control-group">
<label class="control-label">
{{ "Email Address"|_trans }}
</label>
<div class="controls">
<input type="text" ng-model="email.address">
<span class="help-inline"><a href ng-click="remove($index, $event)">{{ "Delete"|_trans }}</a></span>
</div>
</div>
You could create a generic remove method that would take in the array and the item to remove.
<div ng-app="" ng-controller="MyController">
<div ng-repeat="email in emails">{{ email }} <a ng-click="remove(emails, $index)">Remove</a>
</div>
<div ng-repeat="phone in phones">{{ phone }} <a ng-click="remove(phones, $index)">Remove</a>
</div>
</div>
$scope.remove = function(array, index){
array.splice(index, 1);
}
No JS
<div ng-repeat="option in options" ng-init=options=[1,2,3,4,5]>
<button ng-click="options.splice($index,1)">Remove me</button>
</div>
<div ng-app="" ng-controller="MyController">
<div ng-repeat="email in emails as datasource">{{ email }}
<a ng-click="datasource.splice($index,1)">Remove</a>
</div>
<div ng-repeat="phone in phones as datasource">{{ phone }}
<a ng-click="datasource.splice($index,1)">Remove</a>
</div>
</div>
A very simple and convenient way that works cross-browser is to use the 'remove' utility method from the library lodash.
<div ng-repeat="phone in phones">{{ phone }}
<a ng-click="removeItem(phones, phone)">Remove</a>
</div>
In your controller you declare then
//inject lodash dependency
//declare method in scope
$scope.removeItem = function(list, item){
lodash.remove(list,function(someItem) { return item === someItem});
}
You may of course use indexes if you like. See https://lodash.com/docs#remove
If you have used ng-repeat on an object instead of an array, do the following.
<div ng-app="" ng-controller="MyController">
<div ng-repeat="email in emails">{{ email }}
<a ng-click="remove(emails, email)">Remove</a>
</div>
<div ng-repeat="phone in phones">{{ phone }}
<a ng-click="remove(phones, phone)">Remove</a>
</div>
</div>
$scope.remove = function(objects, o){
delete object[o.id];
}
or the more terse
<div ng-app="" ng-controller="MyController">
<div ng-repeat="email in emails">{{ email }}
<a ng-click="delete emails[email.id]">Remove</a>
</div>
<div ng-repeat="phone in phones">{{ phone }}
<a ng-click="delete phones[phone.id]">Remove</a>
</div>
</div>
presumes that the objects look like this
var emails = { '123' : { id : '123', .... } };
var phones = { '123' : { id : '123', .... } };

Categories