Using AngularJS, I have a list of messages that I display in a div that is marked as pre-scrollabe and inside is a bootsrtap list-group to display the individual messages:
<div class="pre-scrollable">
<ul class="list-group">
<li class="list-group-item" ng-repeat="item in MessageList">
<!--Directive to Display Messages-->
</li>
</ul>
</div>
This yields the result that i want, a list of messages through which I can scroll. However I would like to know if there is a way that I can scroll to the top (or even the bottom for that matter) of the list using a JS function?
Related
I am developing a test suite for my AngularJS app using Protractor as my testing framework.
The app's menu is displayed at a fixed location across all pages of the site- when the user hovers the cursor over any of the buttons on the menu, the cursor changes to a pointer, to indicate that that button can be clicked. Each button in the menu represents a particular page of the app- if there are sub-pages belonging to a page when the user hovers the cursor over the menu button for that page, a sub-menu is displayed, with text-buttons for each of the sub-pages.
I am currently working on a test that will test the functionality of the menu- hovering the cursor over one of the buttons on the menu, checking that the sub-menu is displayed, and then hidden again when the cursor is no longer hovering over that menu button, checking that clicking any of the menu buttons/ sub-menu buttons take you to the right page, etc.
The HTML for the menu is written as follows:
<ul id="nav"
class="nav"
data-slim-scroll
data-collapse-nav
data-highlight-active>
<li data-ng-mouseenter="setMenuTop($event)" ng-show="menu.pages.length > 0 || menu.upages.length > 0 || canCreatePage">
<i class="ti-layers"></i><span data-i18n="Pages"></span>
<ul class="text-capitalize">
<li ng-repeat="page in menu.pages"><i class="ti-angle-right"></i><span data-i18n="{{page.title}}"></span></li>
<li ng-repeat="upage in menu.upages">
<div class="nav-menu-divider" data-ng-if="$index === 0"></div>
<a href="#/{{upage.location}}" target="_self">
<i class="ti-angle-right"></i><span data-i18n="{{upage.title}}"></span>
</a>
</li>
<li data-ng-show="canCreatePage">
<div class="nav-menu-divider"></div>
<a href="#/pages/create" target="_self">
<i class="ti-angle-right"></i><span data-i18n="Create Page"></span>
</a>
</li>
</ul>
</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li>...</li>
<li data-ng-mouseenter="setMenuTop($event)">
<i class="ti-settings"></i><span data-i18n="Config"></span>
<ul>
<li ng-repeat="page in menu.config"><i class="ti-angle-right"></i><span data-i18n="{{page.title}}"></span></li>
<li ng-show="platform._id"><a ng-href="#/config/platform/{{platform._id}}" target="_self"><i class="ti-angle-right"></i><span data-i18n="Platform"></span></a></li>
<li ng-show="system._id"><a ng-href="#/config/system/{{system._id}}" target="_self"><i class="ti-angle-right"></i><span data-i18n="System"></span></a></li>
<li><i class="ti-angle-right"></i><span data-i18n="Users"></span></li>
<li><i class="ti-angle-right"></i><span data-i18n="Backup / Restore"></span></li>
<li ng-show="systemActions.dateTime"><i class="ti-angle-right"></i><span data-i18n="Date / Time"></span></li>
</ul>
</li>
<li class="nav-footer">
<span>{{currentTime.localTDZFormat}}</span>
</li>
</ul>
As shown, there are two menu items which have 'sub-menus' associated with them.
I want to test that when the user hovers their cursor over one of the menu-items that have an associated sub-menu, the sub-menu is displayed correctly, and when the cursor leaves the menu-item, the sub-menu is no longer displayed: I have tried to do this with the following test:
it('should display the Pages menu', function() {
browser.waitForAngularEnabled(false);
browser.actions().mouseMove(pagesMenuBtn).perform();
expect(pageVarBrowserBtn.isDisplayed()).toBeTruthy();
browser.actions().mouseMove(userCircle).perform();
expect(pageVarBrowserBtn.isDisplayed()).toBeFalsy();
browser.waitForAngularEnabled(true);
});
The variables used in this test are defined with:
var pagesMenuBtn = element(by.id('pagesMenuBtn'));
var pageVarBrowserBtn = element.all(by.id('menu.pages')).get(0);
var userCircle = element(by.id('icon-user-circle'));
The pageVarBrowserBtn is the first menu-item in the sub-menu displayed when the user hovers their cursor over the pagesMenuBtn.
Currently, when I run the test, the browser opens, navigates to the root page of my app, and hovers the cursor over the pagesMenuBtn element, so that the sub-menu is displayed (I can see it displayed in the browser window that was opened up by the test).
But, I then get an error in the console that says:
Failed: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator By(CSS selector, *[id="menu.pages"])
I don't understand why I'm getting this error...? How can I get a single element from the sub-menu that's being displayed, in order to check that it is the correct item and that clicking it takes the user to the correct location? I can't specify the exact element's ID because it is being created by the ng-repeat, so that's why I'm trying to get it by its position/ array index - 0.
First of all, There may be two reasons why you are getting the above error.
1. Either the locator you are using is wrong.
2. Your script is not waiting until the element is displayed in DOM.
In your case, you have mentioned a wrong locator as element.all(by.id('menu.pages')) because there is no element with id menu.pages is present in your HTML.
Instead of using element.all(by.id('menu.pages')), change it to element.all(by.repeater('page in menu.pages')).get(0) to get the 1st element from the menu list. Also kindly refer Element locators in Protractor to find the list of all available locating strategies that is supported by protractor.
Hope this might help solve your problem!
Did you try using element.all(locator).first() to get the first element form the selector
I'm using the angular drag drop list library for drag/drop of items in a list. Currently I see the item is draggable throughout the body of the page. How can I limit the drag area to only to a particular zone and not everywhere. I checked their API but I don't see any option for that.
In the plunker example you cannot drag and drop every where, only on html element with dnd-draggable
<ul dnd-list="list">
<!-- The dnd-draggable directive makes an element draggable and will
transfer the object that was assigned to it. If an element was
dragged away, you have to remove it from the original list
yourself using the dnd-moved attribute -->
<li ng-repeat="item in list"
dnd-draggable="item"
dnd-moved="list.splice($index, 1)"
dnd-effect-allowed="move"
dnd-selected="models.selected = item"
ng-class="{'selected': models.selected === item}"
>
{{item.label}}
</li>
</ul>
Hey I'm looping thru an array using ng-repeat in my template. The list spits out 9 list elements and I would like change the background color of the selected list element but I want to do it in a way where multiple ones can be selected and the color of the selected ones with a different background color. Initially I had passed $event to the click function on the list element and added a class to event.target but that put the class on all the list elements rather than the selected one.
<ul>
<li class="info-items"
ng-repeat="card in config.cards"
ng-class="{'error-border': emptyCardsArray}">
<div class="inner-text"
ng-model="userSelection.cards"
ng-click="addCard(card.name, $event)">{{card.name}}{{$index + 1}}</div>
</li>
</ul>
HTML:
$(event.target).addClass('active.cards');
JS:
The list that I'm repeating thru unforunately doesn't have a unique ID or I would have passed in the ID and created a condition to check whether the selected items have one and applied the class.
It's a much better practice to simply use ng-class for this.
<ul>
<li class="info-items"
ng-repeat="card in config.cards"
ng-class="{'error-border': emptyCardsArray}">
<div class="inner-text"
ng-model="userSelection.cards"
ng-class="active.cards">{{card.name}}{{$index + 1}}
</div>
</li>
</ul>
I'm creating a sitemap in a custom CMS powered by Angular.
I hide the lower levels of pages and toggle their visibility with a button. I add ng-animate to animate the "opening" of the lower levels of the sitemap.
This works fine for the <ul>, but I would rather have its child <li> enter with a longer transition-delay for every item for a nice waterfall effect and this is where I get stuck.
At first I figured simply adding a transition-delay to the <li> would be sufficient, but for whatever reason I'm even unable to add a regular transition to the <li>. I read about the -stagger class, but it never gets applied.
Markup:
<ul>
<li ng-repeat="page in data"
ng-class="{'children-visible': isVisible}"
ng-init="isVisible = false">
{{page.pagename}}
<button ng-if="page.sub"
ng-click="$parent.isVisible = !isVisible">
</button>
<ul ng-if="page.sub"
ng-show="isVisible"
ng-animate="'animate'">
<li ng-repeat="page in page.sub">
{{page.pagename}}
</li>
</ul>
</li>
</ul>
Here's a picture of the markup if it helps you, er, picture it:
If relevant, I use version 1.2.16 of both angular.js and angular-animate.js.
So, in short: How do I add a stagger/transition delay to children of an element with ng-show?
I am using ui-sortable directive (from angular-ui ) in the view
<ul ui-sortable>
<li ng-repeat="item in items" >
{{item.property1}}
{{item.property2}}
</li>
</ul>
As a result the user can drag and drop to re-sort the items in the browser but this does not update the order of the $scope.items array. How can this be accomplished so that $scope.items array order stays in sync with user initiated drag and drop change in the browser?
You are Missing
ng:model
<ul ui:sortable ng:model="list">
<li ng:repeat="item in list" class="item">{{item}}</li>
</ul>
Please check below working example
Demo
It display the updated array
<div ng:repeat="item in list">{{item}}</div>
Array is updated automatically by the directive