Where to put menu when using angular-snap? - angularjs

I'm using snap.js with AngularJS using the angular-snap.js directive.
https://github.com/jtrussell/angular-snap.js
I'm also using Andy Joslin's angular-mobile-nav.
I'm wondering where I should store the code for the menu:
<snap-drawer>
<p>I'm a drawer! Where do I go in the angular code?</p>
</snap-drawer>
Because this isn't a unique page within the angular-mobile-nav, I'm currently putting the on every page and just using a directive that contains all my menu code/html.
Seems like this could be inefficient as it is loading a new directive on each page, right? Any idea on how to do this better?
Thanks!

So this is what I've done (I also use angular-mobile-nav and angular-snap.js).
This is my HTML Code
<body ng-app="MyApp">
<div snap-drawer>
<ul class="list">
<li ng-repeat="item in sidebar.items" ng-i18next="{{item.name}}" ng-tap="snapper.close();go(item.link)"></li>
</ul>
</div>
<div id="container" snap-content snap-options="snapOpts">
<div mobile-view=""></div>
</div>
</body>
please note that go() is the function to change the page and that I'm using ng-i18next to translate my items. Also ng-tap is a directive which listens for touch events instead of mouse events. With Angular >1.1.5 there's a mobile module, so my ng-tap directive won't be needed anymore.
And by using $rootScope I can put items in the sidebar:
$rootScope.sidebar = {
items: [
{
name: 'item_one',
link: 'page_one'
},
...
]
};
So if you want to change the items in the sidebar, simply override $rootScope.sidebar (not $scope.sidebar) in your controller ;)
If you don't like two animations happen at the same time, you could write a function, which waits for the sidebar to close and then change the page. It could look like this:
$rootScope.waitThenGoTo = function (page, time) {
time = time || 200;
$timeout(function () {
$navigate.go(page);
}, time);
};
If you have still question, please comment. I'll try to update this answer as soon as possible.

Related

AngularJS video issue

I am studying AngularJS by looking at the website http://campus.codeschool.com/courses/shaping-up-with-angular-js/contents and downloaded the videos, then going through the examples on my computer.
Everything went well until the video codeschool_1329.mp4, otherwise called "Shaping_Up_With_Angular_JS_Level_2b". The example works correctly when the logic for selecting the panels is in the HTML code, but when the logic is moved to a controller, it no longer works correctly. Thus I have the relevant HTML code:
<section ng-controller="PanelController as panel">
<ul class="nav nav-pills">
<li ng-class="{active:panel.isSelected(1)}">
<a href ng-click="panel.selectTab(1)">Description</a>
</li>
<!-- Repeated for Specifications and Reviews -->
</ul>
</section>
<div class="panel" ng-show="panel.isSelected(1)">
<h4>Description</h4>
<p>{{product.description}}</p>
</div>
<!-- Repeated for Specifications and Reviews -->
and for the JavaScript code I have:
app.controller('PanelController', function(){
this.tab = 1;
this.selectTab = function(setTab){
this.tab = setTab;
};
this.isSelected = function(checkTab){
return this.tab === checkTab;
};
});
exactly as in the video. The latter is with the Angular module and another Angular controller for the store.
With both Google Chrome and Firefox, when I click on the each of the tabs "Description", "Specifications" and "Reviews", the selected tab is highlighted, as in the video, albeit blue rather than dark purple, but the text that is supposed to be displayed below the selected tab does not show up at all. It looks as if there is some type of a problem with the isSelected function in PanelController with ng-show="panel.isSelected(1)", etc. in the lower part of the HTML code, although it appears to work correctly with ng-class="{active:panel.isSelected(1)}" when the tab is highlighted.
This works correctly when the logic for this is in the HTML code, as I said above, but no matter what I can do, I am unable to get this to work correctly when the logic is in PanelController.
There must be something simple that I am missing, and would be grateful to get this sorted out - many thanks.
<section ng-controller="PanelController as panel">
...
</section>
<div class="panel" ng-show="panel.isSelected(1)">
Only the section element is controlled by the panel controller, but you're trying to use panel.isSelected(1) out of that section. So that can't work.
Put the div inside the section, or wrap everything with another div and move ng-controller="PanelController as panel"to that wrapping div.

ui-sref in parent div overriding all nested links

We have a series of notifications and want to make the overall item clickable to the related item. This has been implemented using ui-sref and functions correctly. However, within that, there are to be a series of nested links that go to other relevant information. The problem at the moment is this parent ui-sref overrides all of these links. I've tried implementing these nested links as standard anchor and ui-sref but it has the same effect. So the hyperlink shows correctly, and when clicking on it, it goes to it for a split second, then reverts back to the ui-sref link.
Here is a code example:
<div class="NotificationItemBalanced">
<div class="notificationItem" ui-sref="community.act({slug: slug, id: id})">
<div class="messageBodyWrapper">
<span class="messageText"><strong><a ui-sref="user.posts({username: username})"></a></strong> commented on your post</span>
</div>
</div>
</div>
Is this related to the ui-sref or is there a specific setting in the routes to fix this?
Thanks
Just create a directive like:
myApp.directive('preventBubbling', function() {
return {
link: function($scope, element) {
element.on("click", function(e) {
e.stopPropagation();
});
}
};
});
And add it to your inner links:
<a ui-sref="user.posts({username: username})" prevent-bubbling></a>
Basically, when you click on a nested element, the click event bubbles up to the DOM tree. So we are simply stopping it to propagate.
https://developer.mozilla.org/en/docs/Web/API/Event/stopPropagation
Update
Also, if your inner links are inheriting properties from parent ui-sref then you should use ui-sref-opts as well:
<a ui-sref="user.posts({username: username})" ui-sref-opts="{inherit: false}" prevent-bubbling></a>

$anchorScroll is not working in AngularJs

I am working on an app that submits the form and get the result from the server which followed by HTML table view. My input form is a bit big which covers whole the screen. When the table comes then I want automatically scroll down at the table view. I used $anchorScroll from angularJs. But I am not able to achieve the result what I want. I also used $timeout to make sure the table is already exist or not and then perform $anchorScroll, but still no success. (based on this solution : Using $location and $anchorScroll to scroll a table row into view
Hear is my code.
HTML
<div data-ng-controller="searchController as searchCtrl" id="scrollArea">
<form>
//HTML input elements
<div class="buttons">
<md-button class="md-primary md-raised" ng-click="searchCtrl.gotoTable('resultTable')">Start</md-button>
</div>
</form>
</div>
<!-- Smart Table for displaying result -->
<div class="rtable" ng-show = "searchCtrl.tableViewData.length > 0" id="resultTable">
//table content
</div>
Controller
angular.module('myApp')
.controller("searchController", function($log, searchService, $scope, $location, $anchorScroll, $timeout){
var self = this;
self.gotoTable = function(resultTable)
{
$timeout(function() {
$location.hash(resultTable);
$anchorScroll();
});
};
});
I dont know why its not working?
Do i need to define the id scrollArea and resultTable in my CSS?
Any help would be appreciated.
Thanks in advance.
UPDATE
Based on Okazari's solution, I tried to put a another div with many br tag above at the very bottom of my HTML. Now When I refresh the page then it automatically scroll to that div tag without clicking Start. this is a bit weird. I also tried to cover the
<div class="rtable" ng-show = "searchCtrl.tableViewData.length > 0" id="resultTable">
tag with another div tag with id = "resultTable".
But still it did not work.
You actually are invoking your function without any parameters
ng-click="searchCtrl.gotoTable()"
whereas in your controller you expect to have one :
self.gotoTable = function(resultTable)
Try something like this
ng-click="searchCtrl.gotoTable('resultTable')"
or this :
self.gotoTable = function()
{
$timeout(function() {
$location.hash("resultTable");
$anchorScroll();
});
};
(just one, not both)
Hope it helped.
EDIT : Pretty sure that you can't go to a hidden div. As i said in comment your ng-show may be evaluated to true when you try to anchorscroll().
Here is a working plunker without ng-show. I'll build a tiny solution to avoid the ng-show issue.
To avoid this side effect, i wrapped the div with ng-show with another div.
<div id="resultTable">
<div class="rtable" ng-show = "searchCtrl.tableViewData.length > 0">
</div>

Detecting an image is fully loaded from a directive, where the directive is not applied to the image element

there are many examples in SO on how we can use an angular directive to know when an image is loaded. The examples describe a directive that is directly applied to the img element like so:
<img ng-src="myimage.jpg" my-great-directive />
And then in the directive "my-great-directive"
we can do an:
element.bind("load" , function(e){ }
And i works great.
However, what if the construct is like this:
<div my-great-directive>
<img ng-src="myimage.jpg" />
</div>
Within my-great-directive, how do I bind to the inside image loaded event?
This is not really a theoretical problem for me. I am using a 3rd party slider called angular-carousel-slider that wraps around like so:
<ul rn-carousel rn-carousel-buffered
rn-carousel-index="mycarousel.index"
rn-carousel-auto-slide="0.3" rn-carousel-pause-on-hover >
<li ng-repeat="slide in slides">
<img ng-src="{{eventBasePath}}{{slide.img}}?rand={{rand}}"/>
</li>
</ul>
I'm trying to modify its code so that it does not slide to the next image unless the current image is fully loaded (to avoid the situation of a fast slider half loading images and moving to the next). I'm stuck on how I can trap this image loaded event inside the directive. Doing element.bind("load") does not work as the directive is not applied to the image element.
Thank you!
Check this working demo: JSFiddle
Use anguler.element to find the img element and bind the event.
In your directive, it should be element.find('img').
angular.module('Joy', [])
.directive('hello', [function () {
return {
restrict: 'A',
link: function (scope, ele) {
var img = ele.find('img');
console.log(img);
img.bind('load', function () {
console.log('img is loaded');
});
}
};
}]);
HTML:
<div ng-app="Joy">
<div hello>
<img ng-src="https://www.google.com.hk/images/srpr/logo11w.png">
</div>
</div>
Update 1
If use ng-repeat, add a $timeout to wait for ng-repeat finishes first. Check working demo: JSFiddle.
Note: this demo is loading a very large image. After the image is loaded, the text img is loaded will be shown.
Update 2
If the event binding is not working, try native image.onload binding (or oncomplete to find images cached). Working demo: JSFiddle.

get ng-click, on injected element, to change the class of an element already in the view?

I have a <ul> that gets populated with the server. But in that controller there is also an iframe. When the <li>'s arrive there is some disconnect between them and the iframe even though they are in the same controller.
When you click one of the li's it should change the class on the iframe but it's not. However, If I move the iframe inside of the ng-repeat that injects the iframe it works.
View
<div class="content" ng-controller="FeedListCtrl">
<ul>
<li ng-repeat="item in items">
<div data-link="{{item.link}}" ng-click="articleShowHide='fade-in'">
<div ng-bind-html="item.title" style="font-weight:bold;"></div>
<div ng-bind-html="item.description"></div>
<!-- it works if i put the iframe here -->
</div>
</li>
</ul>
<!-- doesn't work when the iframe is here -->
<iframe id="article" ng-class="articleShowHide" src=""></iframe>
</div>
Here is the controller. It does an ajax call to get the data for each <li>
Controller
readerApp.controller('FeedListCtrl', ["$scope", "$http", "FeedListUpdate", function ($scope, $http, FeedListUpdate) {
$scope.setFeed = function (url) {
$http.get('feed?id=' + FeedListUpdate.GetCurrentFeedUrl()).success(function (data) {
$scope.items = data.currentFeed.items;
});
};
}]);
When inside of an ng-repeat you are in a different scope which means you are not setting the variable you think you are. Use $parent and that should work. The syntax is:
<div data-link="{{item.link}}" ng-click="$parent.articleShowHide='fade-in'">
Side note for others finding this - sometimes adding curly brackets helps as well. For more information on ng-class see here: http://docs.angularjs.org/api/ng/directive/ngClass
An Example
In case anyone wants to see this in action, I put together an example demonstrating a few ways to set the class as well as demonstrating the issue in scope (See: http://plnkr.co/edit/8gyZGzESWyi2aCL4mC9A?p=preview). It isn't very pretty but it should be pretty clear what is going on. By the way, the reason that methods work in this example is that the scope doesn't automatically redefine them the way it does variables so it is calling the method in the root scope rather than setting a variable in the repeater scope.
Best of luck!

Resources