Angular Scroll on Click - angularjs

I am having an issue getting Angular Scroll to work.I am trying to scroll from the landing div to another section on the page with a button click. My code formatted really strangely, so let me know if further clarification is needed.
HTML
<div class="cover">
<div class="big-logo">
<i class="fa fa-trello"></i>
<span> My Kanban</span>
<br>
<button class="arrow" ng-click="bc.toLists()" du-smooth-scroll>
<i class="fa fa-angle-double-down fa-sm animated flash infinite" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="story-board content">
<button class="add-list" ng-click="bc.addingList = !bc.addingList">
Add List
</button>
<div ng-if="bc.addingList">
<form ng-submit="bc.addList(bc.newList)">
<input style="margin-left: 5px" ng-model="bc.newList.name"/>
<button type="submit">+</button>
</form>
</div>
<div class="list" ng-repeat="list in bc.lists">
<button style="font-size: 10px;background: none;border:none; color: black" ng-click="bc.removeList(list)">x</button>
<list-component list-obj="list"></list-component>
</div>
</div>
init.js
angular.module('kanban', ['duScroll'])
app.js
angular.module('kanban')
.component('boardComponent', {
templateUrl: 'app/components/board/board.html',
controller: BoardController,
controllerAs: 'bc'
})
BoardController.$inject = ['EsService']
function BoardController(EsService) {
var bc = this;
bc.lists = EsService.getLists();
bc.addingList = false;
bc.removeList = function(list){
EsService.removeList(list.id);
}
bc.addList = function(list){
EsService.createList(list);
bc.newList = {};
}
bc.toLists = function() {
bc.cover = angular.element(document.getElementsByClassName('cover'));
bc.content = angular.element(document.getElementsByClassName('content'));
bc.cover.scrollTo(bc.content, 0, 1000);
}
}

For a JQuery free answer, you can use $anchorScroll
Create your anchor link:
<button ng-click="$ctrl.scrollTo('anid')">Scroll</button>
Create the anchor to scroll to:
<div id="anid">Land here</div>
Then your controller:
controller: function($anchorScroll) {
this.scrollTo = function(id) {
$anchorScroll(id);
}
}

I would recommend letting your controller handle the scrolling as opposed to the directives. You will have much tighter control that way and can therefore debug any issues.
Here's an example using the scrollToElement method. Once you have this logic in place you can switch it out to any method you need.
Here's a working demo
angular
.module('app', ['duScroll'])
.component('cmpExample', {
templateUrl: 'path/to/template.html',
controller: function($document) {
var vm = this;
vm.scrollTo = function(id) {
$document
.scrollToElement(
angular.element(document.getElementById(id)), 0, 1000
);
}
}
});
html
<button ng-click="$ctrl.scrollTo('target')">
<div id="target">Content further down the page</div>

Related

Unable to change ng-href onClick event

I have a footer with a button in my angular app. The button has an ng-href attribute which should change during the ng-click event to affect the routing mechanism. For some reason I cant make this work. The ultimate goal is to append numbers, 1 to five each button click.
The footer is a component:
app.component('footerx', {
bindings: {
},
templateUrl: 'views/footer.html',
controller: function () {
this.buttonText = "Next";
var self = this;
var i = 1;
this.changeHref= function () {
self.questionIndex=i;
i++;
}
}
});
Footer HTML:
<footer class="footer">
<div class="container">
<a class="btn btn-primary" ng-click="$ctrl.changeHref()" ng-href="#/quiz/{{questionIndex}}" id="btn">{{$ctrl.buttonText}}</a>
</div>
</footer>
Routing JS part:
...
.when("/quiz/:index", {
templateUrl: "views/questionPage.html",
controller: "questionController"
})
...
EDIT:
Right now the url does not fully change. This means it does not have the questionIndex. It looks like this:
http://localhost/myApp/#/quiz/
Use "#/quiz/{{$ctrl.questionIndex}}
<footer class="footer">
<div class="container">
<!-- REMOVE
<a class="btn btn-primary" ng-click="$ctrl.changeHref()"
ng-href="#/quiz/{{questionIndex}}" id="btn">
{{$ctrl.buttonText}}
</a>
-->
<!--ADD -->
<a class="btn btn-primary" ng-click="$ctrl.changeHref()"
ng-href="#/quiz/{{$ctrl.questionIndex}}" id="btn">
{{$ctrl.buttonText}}
</a>
</div>
</footer>

Show/Hide Angular Directive On Button Click

I have a HTML page with three buttons. I also have two Angular directives. What I'm trying to accomplish is when button a is clicked, I want directive 1 to show and directive 2 to hide. When button 2 is clicked, I want directive 1 to hide and directive 2 to show. Here is are my directives:
.directive('topPosts', function () {
return {
restrict: 'E',
templateUrl: 'topPosts.html',
controller: 'PostsController'
}
});
.directive('otherPosts', function () {
return {
restrict: 'E',
templateUrl: 'otherPosts.html',
controller: 'PostsController'
}
});
here is my controller:
.controller('PostsController', ['$scope', 'PostsFactory', function($scope, PostsFactory) {
$scope.posts = [];
$scope.showTopPosts = true;
$scope.showOtherPosts = false;
$scope.topPosts = function() {
$scope.showTopPosts = true;
$scope.showOtherPosts = false;
};
$scope.otherPosts = function() {
$scope.showTopPosts = false;
$scope.showOtherPosts = true;
};
$scope.areTopPosts = function(posts) {
return posts.privacy === 'public' && posts.comments > 10 && posts.views > 9000 && posts.title.length < 40;
};
$scope.areOtherPosts = function(posts) {
return posts.comments <= 10 && posts.views <= 9000 && posts.title.length >= 40;
};
var init = function() {
PostsFactory.getPosts.success(function(data) {
$scope.posts = data;
});
};
init();
}]);
here is my partial that holds both directives:
<div class="container">
<top-posts ng-show='showTopPosts'></top-posts>
<other-posts ng-show='showOtherPosts'></other-posts>
</div>
and here is my index.html:
<body ng-controller='PostsController'>
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="/main"></a>
</div> <!-- END NAVBAR-HEADER -->
</div> <!-- END CONTAINER-FLUID -->
</nav>
<div class="container">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="topPosts()">Top Posts</button>
<button type="button" class="btn btn-default" ng-click="otherPosts()">Other Posts</button>
<!-- <button type="button" class="btn btn-default" ng-click="dailyTopPost()">Daily Top Post</button> -->
</div>
</div>
<div ng-view class='slide-animation'></div>
What's currently happening is the functions are getting called, but the directives are not showing/hiding on the button clicks.
I put work code in a codepen and it seems to be working fine http://codepen.io/arthur_souviron/pen/pEMMaJ/
I think your issue come from the way you store $scope.showTopPosts
and $scope.showOtherPosts. Try to store them inside an object instead of setting them directly under $scope
Eg :
$scope.data = {
showTopPosts: true,
showTopPosts: false
}
and in your template : <top-posts ng-show="data.showTopPosts"></top-posts>
Simply add a div before the directive:
<div class="container">
<div ng-show='showTopPosts'><top-posts ></top-posts></div>
<div ng-show='showOtherPosts'><other-posts ></other-posts></div>
</div>

Bind data to modal

I am trying to pass some data with a function to display on a modal, yet the usual approaches to binding are not working, I was hoping someone could point me in the right direction.
$scope.openModal = function (obj) {
//$scope.data = {type: obj.type, descriptions: obj.description, isDone: obj.isDone, createDate: obj.createDate, priority: obj.priority};
$scope.data = obj;
console.log($scope.data);
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'modalTemplate.html',
controller: 'View1Ctrl',
resolve: {
data: function () {
return $scope.data;
}
}
});
}
Template
<!-- MODAL -->
<div>
<div ng-controller="View1Ctrl">
<script type="text/ng-template" id="modalTemplate.html">
<div class="modal-header">
<h3 class="modal-title">Item Details</h3>
</div>
<div class="modal-body">
<ul>
<li>Type: <span ng-model="data.type"></span></li>
<li>Description: <span ng-model="data.description"></span></li>
<li>Date: <span ng-model="data.createDate"></span></li>
<li>Priority: <span ng-model="data.priority"></span></li>
<li>Finished: <span ng-model="data.isDone"></span></li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="$close()">OK</button>
</div>
</script>
</div>
Also tried {{data.type}} etc, and ng-bind. I now my $scope.data is populated because it is showing as much in the console.
You should inject data (resolve object) into your modal controller then add it to the $scope object.
You should remove ng-controller="View1Ctrl" from template.

Best way to create a reusable modal window in angularjs

I am using html5, angularjs, bootstrap. So each one of them gives many options to create a modal window. Whole of my website has 2 things, one is confirmation dialog or form dialog. So which is the best reusable approach. Should i use html5 or create a directive ?
As mentioned in the comments ui-bootstrap Modal is very useful.
Just for an example here is a factory for confirm modal that you can extend according to your use case:
yourApp.factory("dialog", ["$modal",
function($modal) {
var dialogService = {
confirm: function(options) {
var modalInstance = $modal.open({
templateUrl: 'partials/confirm-modal.html',
controller: ['$scope',
function($scope) {
$scope.header = options.header;
$scope.body = options.body;
$scope.confirmText = options.confirmText || "Close";
$scope.cancelText = options.cancelText || "Confirm";
$scope.hideCancelButton = options.hideCancelButton;
$scope.cancel = function() {
modalInstance.dismiss('cancel');
};
$scope.confirm = function() {
modalInstance.close();
};
}
]
});
return modalInstance.result;
}
}
}
])
And here is your template:
<div class="modal-header">
<button type="button" data-dismiss="modal" aria-hidden="true" class="btn close" ng-click="cancel()">×</button>
<h4 id="noteLabel" class="modal-title">{{header}}</h4>
</div>
<div class="modal-body">
<p ng-bind-html="body" style="font-size: 16px"></p>
</div>
<div class="modal-footer">
<button ng-show="!hideCancelButton" class="btn btn-default" ng-click="cancel()">{{cancelText}}</button>
<button ng-click="confirm()" class="btn btn-primary">{{confirmText}}</button>
</div>

Method display on the scope is not executed

I have a set of directives that share a scope
Update:
The code is available as a plunk here http://plnkr.co/edit/JZ77bsZgGrw6N4K718Is?p=preview
todo-item:
app.directive("todoItem",function(DeleteTodo,$log){
var dirDefObj = {
restrict:'E',
templateUrl:'app/templates/todo.html',
scope:{
todo:'=value'
},
controller:function($scope){},
replace:true
};
return dirDefObj;
});
template:
<div class="ui card">
<todo-formui ng-show="todo.editMode"></todo-formui>
<todo-cardui ng-show="!todo.editMode"></todo-cardui>
</div>
There are two directives that inherit the scope of this directive:
todo-cardui
app.directive('todoCardui',function(){
var dirDefObj = {
restrict:'E',
templateUrl:'app/templates/display-todo.html',
scope:false,
replace:true,
controller:function($scope)
{
$scope.clickDone = function clickDone(){
//two tasks (1)toggle the done value on the todo (2) toggle the btnText on the todo
$scope.todo.done = !$scope.todo.done;
$scope.todo.btnText = $scope.todo.done?'Reinstate':'Done';
};
$scope.remove = function remove()
{
DeleteTodo.delete($scope.todo);
$scope.$emit('todo:deleted',$scope.todo);
};
$scope.edit = function edit(value)
{
$scope.todo.editMode = true;
$scope.savedState = angular.extend({},$scope.todo);
};
}
};
return dirDefObj;
});
template:
<div>
<div class="content">
<i class="right floated blue pencil icon" ng-click="edit()"></i>
<header class="ui medium header">
<span ng-class="{'done-todo':todo.done,'normal-todo':!todo.done}">{{todo.task}}</span>
</header>
<div class="description">
<p>{{todo.description}}</p>
</div>
</div>
<div class="extra content">
<button class="ui small green toggle button floated left" ng-click="clickDone()">{{todo.btnText}}</button>
<button class="ui small red button floated left" ng-click="remove()">Delete</button>
</div>
</div>
todo-formui:
app.directive("todoFormui",function(EditService){
var dirDefObj = {
restrict:'E',
templateUrl:'app/templates/edit-todo.html',
scope:false,
controller:function($scope){
$scope.display = function display(){
console.log("Inside the edit to preview function");
$scope.editMode = false;
};
$scope.save = function(){
EditService.edit($scope.todo);
};
$scope.discard = function(){
$scope.todo={
task:'',
dscription:'',
btnText:''
};
$scope.todo = $scope.savedState;
};
},
replace:true
};
return dirDefObj;
});
template:
<div ng-class="{description:show_modal,content:!show_modal}">
<i class="right floated blue unhide icon" ng-click="display()"></i>
<form class="ui small form">
<div class="field">
<label>Task</label>
<input type="text" name="task" placeholder="What do you want to do?"ng-model="todo.task">
</div>
<div class="field">
<label>Description</label>
<textarea ng-model="todo.description"></textarea>
</div>
<div class="two fields">
<button class="ui red button floated right">Discard</button>
<button class="ui submit green button floated right" ng-click="save()">Save</button>
</div>
</form>
When executing the code,I found that the display function in todo-formui would not execute,no matter where I put it or what I tried to do.The save function in the same scope runs with no problems.
In your preview function(as mentioned in plunker), you have to update the scope as
$scope.todo.editMode = false;
instead of
$scope.editMode = false;
then the preview will be avaliable
Hope this helps
It's because the icon is under another html element and the click event isn't triggered. Add a clear after the "preview" icon (which is floated) to push the form where it should be. Use some DOM inspector and you will soon realize the problem.

Resources