I am trying to create a directive for two views. basically we have a modal, with header and footer. When we click on continue button in footer, the modal body should be alone changed displaying question 2 as a new view with header and footer fixed. How would i achieve this using directives?
Do i need to create individual directives for each view?
Here is my code
modal.html -
<section>
<header class="modal-header">
</header>
<div class="modal-body">
question 1
</div>
<footer>
<button>{{'BACK' | translate}}</button>
<button type="submit" ng-click="showQuestion(2)">{{'CONTINUE' | translate}}</button>
</footer>
</section>
directive.js
'use strict';
angular.module('OrderApp').directive('modalQuestions', [function () {
function getQuestions() {
return {
restrict: 'A',
templateUrl: 'modules/common/modals/modal.html',
scope: true
};
}
]);
It sounds like you may want to use the ngSwitch directive:
<section>
<header class="modal-header">
</header>
<div class="modal-body" ng-switch="questionNumber">
<div ng-switch-when="1">
question 1
</div>
<div ng-switch-when="2">
question 2
</div>
</div>
<footer>
<button>{{'BACK' | translate}}</button>
<button type="submit" ng-click="showQuestion(2)">{{'CONTINUE' | translate}}</button>
</footer>
</section>
Then on your controller:
$scope.questionNumber = 1;
$scope.showQuestion = function (questionNumber) {
$scope.questionNumber = questionNumber;
}
When $scope.questionNumber is updated, ngSwitch will change which of the divs it shows. Everything else on the page will remain the same.
Related
I'm trying to use in modal (Mobile Angular JS ), but I have not found , any way of setting controller for my modal inside my main controller , and pass parameters. My application is just mobile , it would be wrong to use ui- bootstrap ?
Html
<div ui-content-for="title">
<span>Employerss</span>
</div>
<div class="scrollable" ui-state="searchBar">
<div class="scrollable-content" ui-scroll-bottom='bottomReached()'>
<div class="list-group" style="height:80px;">
<a ng-repeat="employers in employerss" ng-click="select(employers)" class="list-group-item">
<p>{{employers.name | limitTo:70}}...</p>
</a>
</div>
</div>
</div>
<div ui-content-for="modals">
<div ng-include="'modal/modalemployers.html'" ng-controller="modalEmployersController"></div>
</div>
Modal
<div class="modal" ui-if='modalemployers' ui-state='modalemployers'>
<div class="modal-backdrop in"></div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close"
ui-turn-off="modalemployers">
×
</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>{{test}}</p>
</div>
<div class="modal-footer">
<button ui-turn-off="modalemployers" class="btn btn-default">Close</button>
<button ui-turn-off="modalemployers" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
Angular JS
var app = angular.module('apphome', [
"ngRoute",
"ngTouch",
"mobile-angular-ui",
"mobile-angular-ui.core",
"mobile-angular-ui.components"
]);
.........
.........
app.controller('employersController', function ($scope, $http) {
$scope.employerss = [];
$scope.select = function (item) {
$scope.Ui.turnOn('modalemployers');
}
getEmployers($http, function return(data) {
$scope.employers = data;
});
});
app.controller('modalEmployersController', function ($scope) {
$scope.test = "teste";
});
I Need (I am confused if I can use bootstrap -ui , without jeopardizing my application because it is just mobile. I need to know if the bootstrap -ui will work well . Mobile phones with small screen will use the application can not break the layout.)
$scope.select = function (item) {
var modalInstance = $modal.open({
templateUrl: 'modalemployers.html',
controller: 'modalEmployersController',
size: size,
resolve: {
item: function () {
return item;
}
}
});
}
Thanks all!
Angular UI Bootstrap just provides Angular templates and extensions for Bootstrap CSS. Since Bootstrap CSS supports mobile devices, the Angular UI Bootstrap library does as well.
Note that the only dependencies of Angular UI Bootstrap are Angular >= 1.3.x and Bootstrap CSS >= 3.x.
I have my modal set up as so
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Confirm</h3>
</div>
<div class="modal-body">
<p>Are you sure you want to remove Two Factor Authentication from your profile?</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="removeSetting()">Yes</button>
<button class="btn btn-warning" ng-click="$dismiss()">Cancel</button>
</div>
</script>
Hitting the cancel button does what it should, simply closes the modal. My problem comes when a user hits the yes button. My function removeSetting() never gets executed.
$scope.removeSetting = function() {
TwoFactorAuthenticationService.removetAuthetication().then(function(data) {
$scope.busy3=false;
notifyService.alert("error", notifyService.getAlertText('2FactorRemovedToken'));
$scope.busy=true;
$timeout(function() {
$scope.templateUrl = 'twofactorsetup/step1.html';
}, 3000);
}, function() {
notifyService.alert("error", notifyService.getAlertText('2FactorRemoveTokenFailed'));
});
};
That is the function that should be called and executed. What am I missing?
Place code like this in modal initialize
$modal.open({
templateUrl: 'myModalContent.html',
scope: $scope,
controller: function($scope, $modalInstance) {
$scope.removeSetting = function() {
//place your code here or call function from parent scope
$scope.$parent.removeSetting();
$modalInstance.dismiss('cancel');
};
}
});
You don't need scope parameter if not using parent scope.
Or you can use call function from parent scope from template like this (by using $parent.removeSetting() call)
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Confirm</h3>
</div>
<div class="modal-body">
<p>Are you sure you want to remove Two Factor Authentication from your profile?</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="$parent.removeSetting()">Yes</button>
<button class="btn btn-warning" ng-click="$dismiss()">Cancel</button>
</div>
</script>
I have an isolated scope directive that has its own controller.
The directive's template has access to that controller, except inside an ng-repeat where the entire controller is out of scope.
I don't know how to fix it.
If you have an ng-repeat inside an ng-controller, children of the ng-repeat inherit the functions of the ng-controller.
I would have thought that would be the case with custom directives, too - children inside the ng-repeat could still see the directive's controller - but as far as I can tell, they can't.
I'm still getting up to speed with Angular, so a nudge in the right direction would be appreciated. A downright answer would be appreciated even more. Something to do with transclusion? With which is getting compiled first?
Here is the directive:
angular.module('surverApp')
.directive('surveyItems', function () {
return {
restrict: 'E',
scope: {
itemList: '=',
query: '='
},
templateUrl: 'views/directives/survey-items.html',
replace: true,
controller: 'SurveyItemsCtrl',
controllerAs: 'ctrl',
bindToController: true
};
})
.controller('SurveyItemsCtrl', function(){
var ctrl = this;
ctrl.disableEdit = true;
ctrl.disableToolbar = false;
ctrl.showForm = false;
ctrl.showDuplicate = false;
ctrl.showTrash = false;
ctrl.deleteItem = function(item) {
console.log('ctrl.item in DELETE ITEM' ,item)
.... functions removed for brevity
};
});
And here is its template. None of its functions fire.
<div>
<pre>ctrl = {{ctrl | json}}</pre> <<<<<=== THIS SHOWS THE CONTROLLER IS IN SCOPE
<div ng-repeat="item in ctrl.itemList | filter:ctrl.query" class="ubi-box container-fluid">
<pre>ctrl = {{ctrl | json}}</pre> <<<<<=== THIS SHOWS THE CONTROLLER IS NOT IN SCOPE
<standard-right-toolbar ctrl="ctrl"></standard-right-toolbar>
<h4>{{item.name}}</h4>
<div ng-show="ctrl.showForm" class="ubi-box container-fluid">
<!-- <survey-form model="item" disable-edit="ctrl.disableEdit" reset-fn="item = ctrl.resetUpdateFn(item)" submit-fn="ctrl.submitUpdateFn()" close-fn="ctrl.hideFormFn()"></survey-form> -->
<survey-form model-el="item" disable-edit-el="ctrl.disableEdit" reset-fn="ctrl.resetUpdateFn(form,model)" submit-fn="ctrl.submitUpdateFn(form)" close-fn="ctrl.hideFormFn()"></survey-form>
<pre>model = {{item | json}}</pre>
</div>
<div ng-show="ctrl.showDuplicate" class="ubi-box container-fluid">
<standard-right-close-bar close-fn="ctrl.hideDuplicateFn()"></standard-right-close-bar>
<h4 class="col-xs-12">Duplicating a survey will copy all the details and questions over to a new survey.</h4>
<h3 class="col-xs-10">Click the copy button to procede.</h3>
<button class="btn btn-lg btn-primary" type="button" ng-click="ctrl.copy(item)" title="Duplicate">
<span class="glyphicon glyphicon-duplicate"></span>
</button>
</div>
<!-- <div ng-show="ctrl.showTrash" class="ubi-box container-fluid"> -->
<div ng-show="ctrl.showTrash" class="ubi-box container-fluid">
<standard-right-close-bar close-fn="ctrl.hideTrashFn()"></standard-right-close-bar>
<h4 class="col-xs-12">Deleting a survey is a very serious matter. It will permanently remove every question and every answer in every questionnaire in every edition in the survey.</h4>
<h3 class="col-xs-10">Click the trashcan only if you are sure!</h3>
<button class="btn btn-lg btn-danger" type="button" ng-click="ctrl.deleteItem(item)" title="Delete">
<span class="glyphicon glyphicon-trash"></span>
</button>
</div>
</div>
<div>
PS I had it working fine inside an ng-controller. But then I read ng-controllers are being outlawed in Angular 2.0, so I thought I'd get in some practice using directive controllers rather than ng-controllers and I wrapped the ng-repeat in a directive instead of an ng-controller.
So far, so stumped . . .
I'd like to avoid repeating myself with my page header as much as possible. So, I'm thinking doing something like this:
<header>
<title>Forms</title>
<actions>
<action ng-click="showNewFormModal()">New Form</action>
<action ng-click="showHelp()">?</action>
</actions>
</header>
which would desirably result in
<div class="page-header">
<div class="left">
<h3>Forms</h3>
</div>
<div class="right">
<a class="btn btn-default" role="button" ng-click="showNewFormModal()">New Form</a>
<a class="btn btn-default" role="button">?</a>
</div>
<div class="clearfix"></div>
</div>
As you can see, <header> contains custom elements, <title>, <actions>, and <action>, which are specific to only the <header> element.
Is such a thing possible in Angular? How would I accomplish this?
See this jsbin I put together which shows how it can be done with custom directives. I had trouble using the names header and title (though I'm almost positive it can be done), for the example, I've user my-header and my-title
Anyways, I've put together the first two elements, the rest will follow the same convention. You can also set up dependencies and scope on each directive, i.e. an action must be inside of an actions parent element
app.directive('myHeader', function() {
return {
restrict: "E",
transclude: true,
template: "<div class='page-header'><div ng-transclude></div></div>"
};
});
app.directive('myTitle', function() {
return {
restrict: "E",
transclude: true,
template: "<div class='left'><div ng-transclude></div></div>"
};
});
Your HTML will look like:
<my-header>
<my-title>Forms</my-title>
</my-header>
And the generated HTML will look like:
<my-header>
<div class="page-header">
<div ng-transclude="">
<my-title class="ng-scope">
<div class="left">
<div ng-transclude="">
<span class="ng-scope">Forms</span>
</div>
</div>
</my-title>
</div>
</div>
</my-header>
I'm trying to paginate my blogroll using AngularJS and the MEAN Stack. I have my Articles (blog posts) controller set up, and I've list.html to display everything. I can either get all the blogs to display, or I can get the pagination to increment, but I can't get the blogroll to show 5 items at a time and increment with the pagination.
angular.module('mean.articles')
.controller('ArticlesController', ['$scope', '$routeParams', '$location', 'Global', 'Articles', function ($scope, $routeParams, $location, Global, Articles) {
$scope.global = Global;
$scope.currentPage = 0;
$scope.pageSize = 5;
//I've my create, update and delete methods here.
$scope.find = function() {
Articles.query(function(articles) {
$scope.articles = articles;
});
};
$scope.numPages = function() {
return Math.ceil($scope.Articles.length / $scope.pageSize);
};
And here's my list.html:
<div class="container" style="width:900px; margin:auto">
<div class="container" style="width:600px; float:left">
<section data-ng-controller="ArticlesController" data-ng-init="find()">
<ul class="articles unstyled" style="width:600px">
<li data-ng-repeat="article in articles | filter:search | limitTo:pageSize">
<h2><a data-ng-href="#!/articles/{{article._id}}">{{article.title}}</a></h2>
<div>{{article.content}}</div>
<div>{{article.tags}}</div>
<h4><small>
<div class="well well-small text-center" style="width:300px">
<div style="margin:auto">
<span>{{article.created | date:'medium'}}</span> /
<span>{{article.user.name}}</span>
</div>
</div>
</small></h6>
</li>
</ul>
<h1 data-ng-hide="!articles || articles.length">No articles yet. <br> Why don't you Create One?</h1>
<button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
Previous
</button>
{{currentPage+1}}/{{numPages()}}
<button ng-disabled="currentPage >= numPages()-1" ng-click="currentPage=currentPage+1">
Next
</button>
</section>
</div>
<div class="container" style="width:300px; float:left">
<input type="text" ng-model="search" placeholder="Enter your search terms" />
</div>
http://jsfiddle.net/2ZzZB/56/ from Pagination on a list using ng-repeat. It looks like the main thing you're missing is a way to indicate where to start your ng-repeat. The fiddle I linked to solves it by creating a startFrom filter.