why does angular animation within directive execute on page load? - angularjs

I have an angular ngSwitch animation applied in 2 different ways, one within a directive, and one on the html page. The animation within the directive fires on page load. Why is this occurring and how to fix?
plunker: http://plnkr.co/edit/japvWhohw8JaDWkDBUAf?p=preview
index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="//code.angularjs.org/1.2.20/angular.js"></script>
<script src="//code.angularjs.org/1.2.20/angular-animate.js"></script>
<script src="script.js"></script>
</head>
<body id="ng-app" ng-app="myApp" ng-controller="myAppCtrl">
Change value
<br><br>
<span><strong>Through directive</strong><small> - animation fires on page load</small></span>
<div value-rotate="myVal" style=""></div>
<br>
<span><strong>Not through directive</strong><small> - animation does no fire on page load</small></span><br>
<span class="value-rotate" ng-switch on="myVal">
<div class="value-rotate__value" ng-switch-when="true">value is {{ myVal }}</div>
<div class="value-rotate__value" ng-switch-when="false">value is {{ myVal }}</div>
</span>
</body>
</html>
script.js
'use strict';
angular.module('myApp', ['valueRotate'])
.controller('myAppCtrl', function($scope) {
$scope.myVal = true;
});
angular.module('valueRotate', ['ngAnimate'])
.directive('valueRotate', function() {
return {
scope: {
value: '=valueRotate'
},
templateUrl: 'value-rotate.html',
link: function (scope, element) {
element.css({ position: 'relative', overflow: 'hidden' });
}
};
});
style.css
.value-rotate {
position: relative;
display: inline-block;
}
.value-rotate__value {
padding: 10px;
}
.value-rotate__value.ng-animate {
-webkit-transition: all cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.5s;
transition: all cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.5s;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.value-rotate__value.ng-leave.ng-leave-active,
.value-rotate__value.ng-enter {
top: -50px;
}
.value-rotate__value.ng-leave,
.value-rotate__value.ng-enter.ng-enter-active {
top: 0;
}
value-rotate.html (directive template)
<span class="value-rotate" ng-switch on="value">
<div class="value-rotate__value" ng-switch-when="true">value is {{ value }}</div>
<div class="value-rotate__value" ng-switch-when="false">value is {{ value }}</div>
</span>

Related

horizontal scrollbar on click of button angularjs

I am trying to obtain horizontal scroll using buttons.
I have a container which has several elements(which can be more than 3 , getting values from backend) stacked horizontally and I want to scroll through them using the buttons. Also i want to hide those buttons when there is no scrollbar.
This is very easy and usefull:
angular.module('anchorScrollOffsetExample', [])
.run(['$anchorScroll', function($anchorScroll) {
$anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
}])
.controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
function($anchorScroll, $location, $scope) {
$scope.gotoAnchor = function(x) {
var newHash = 'anchor' + x;
if ($location.hash() !== newHash) {
// set the $location.hash to `newHash` and
// $anchorScroll will automatically scroll to it
$location.hash('anchor' + x);
} else {
// call $anchorScroll() explicitly,
// since $location.hash hasn't changed
$anchorScroll();
}
};
}
]);
body {
padding-top: 50px;
}
.anchor {
border: 2px dashed DarkOrchid;
padding: 10px 10px 200px 10px;
}
.fixed-header {
background-color: rgba(0, 0, 0, 0.2);
height: 50px;
position: fixed;
top: 0; left: 0; right: 0;
}
.fixed-header > a {
display: inline-block;
margin: 5px 15px;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-anchor-scroll-offset-production</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="anchorScrollOffsetExample">
<div class="fixed-header" ng-controller="headerCtrl">
<a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
Go to anchor {{x}}
</a>
</div>
<div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
Anchor {{x}} of 5
</div>
</body>
</html>

Angularjs popup/modal content

I'm in a AngularJS learning-by-doing stage, and this I can not figure out nor been able to find an answer for.
What I'm doing:
On ng-click I call a function in my controller, that $http-loads html-content (some divs and a form), that I "paste" to my ng-bind-html inside a div in my template.
That's working fine - but my problem is, that I'm not able to set values to the ng-models or {{someText}} in the loaded data. I get "undefined" on the elements inside the div (a modal-div with random content and therefore not a static part of my template).
I'm not using Bootstrap or anything similar.
What can I do to make the data a part of my scope - or to achieve what I want in another way (a modal div with random content)?
I can post some code, if that's any help to you. And when you answer please remember, I'm a totally newbie! :-)
-
My directive:
workApp.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.boxWidth) scope.dialogStyle.width = attrs.boxWidth;
if (attrs.boxHeight) scope.dialogStyle.height = attrs.boxHeight;
scope.hideModal = function() {
scope.show = false;
};
},
templateUrl: 'app/tpl/modal.html'
};
});
States:
.state('main', {
abstract: true,
templateUrl: tplMain
})
// PROJECTS
.state('main.projects', {
url: '/projects',
templateUrl: 'app/views/projects/project-list.html',
controller: 'projectListCtrl'
})
.state('main.projectdetails', {
url: '/projects/:projectId/details',
templateUrl: 'app/views/projects/project-details.html',
controller: 'projectDetailsCtrl'
})
The HTML (nested views):
<!-- main -->
<div ui-view>
<!-- main.projects -->
<div ui-view>
<a ng-click="newProject()">New project</a>
</div>
</div>
<modal-dialog>{{message}}</modal-dialog>
Controller:
workApp.controller('projectListCtrl', function($scope, $rootScope, $http) {
$scope.newProject = function() {
$scope.message = '<div>Some HTML here...</div>'; // Loaded from $http.get
$scope.modalOpen = true;
}
});
The first of my two problems is, that the modal doesn't show when i call newProject(). And I think it's because of the states / nested views (my modal-dialog is in another view)? If I copy the modal-dialog to my main.projects state it works.
The second is that {{message}} can't contain bindings, so I'm not able to bind fx. $scope.modal.title to {{modal.title}} in the HTML.
UPDATE:
I've found a working example that dynamically includes a html-file:
<div id="modal" ng-class="{ open: modal.data.visible }" ng-include="'app/views/' + modal.data.include"></div>
And in the controller:
$scope.modal.data = {
include: 'projects/project-data.html',
visible: true,
title: 'New project',
subtitle: 'Enter project data',
projectName: 'My first project',
projectCompany: 'The Project Company'
}
This seems to work very well - but is it bad practice versus a directive (that I still can not get to work).
If I understand your use case, you are just wanting to pass data between the html and your modal. Here is an Plunker I found that you can review. I've done similar things like this and a directive is the best solution I've found.
HTML
<!DOCTYPE html>
<html ng-app="app">
<head>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" data-semver="3.3.2" data-require="bootstrap#*" />
<script src="http://code.jquery.com/jquery-2.1.4.min.js" data-semver="2.1.4" data-require="jquery#*"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js" data-semver="3.3.2" data-require="bootstrap#*"></script>
<script data-require="angular.js#1.3.15" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="indexCtrl">
<h4 style="margin-left: 10px;margin-top: 20px;">Display a modal dialog with AngularJS</h4>
<hr />
<button ng-click="toggleModal()" class='btn btn-warning btn-sm' style="margin: 5px 0px 10px 10px;width: 150px;">Open Modal</button><br />
<!-- Angular JS Directive Modal -->
<modal-dialog box-width="400px" box-height="150px" show="modalShown">
<div class="row">
<div class="col-md-12">
<h3>Header</h3>
<hr style="border-top:1px solid darkblue"/>
</div>
</div>
<div class="row">
<div class="col-md-12">
<!-- This is an important message -->
{{message}}
</div>
</div>
</modal-dialog>
</body>
</html>
modalDialog.html
<div class='ng-modal' ng-show='show'>
<div class='ng-modal-overlay' ng-click='hideModal()'></div>
<div class='ng-modal-dialog' ng-style='dialogStyle'>
<div class='ng-modal-close' ng-click='hideModal()'>X</div>
<div class='ng-modal-dialog-content' ng-transclude></div>
</div>
</div>
script.js
angular.module('app', []);
angular.module('app').controller('indexCtrl', function($scope) {
$scope.modalShown = false;
$scope.message= "This is an important message!"
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
});
angular.module('app').directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
transclude: true, // Insert custom content inside the directive
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.boxWidth) {
scope.dialogStyle.width = attrs.boxWidth;
}
if (attrs.boxHeight) {
scope.dialogStyle.height = attrs.boxHeight;
}
scope.hideModal = function() {
scope.show = false;
};
},
templateUrl: 'modalDialog.html'
};
});
CSS
/* Styles go here */
.ng-modal-overlay {
/* A dark translucent div that covers the whole screen */
position:absolute;
z-index:9999;
top:0;
left:0;
width:100%;
height:100%;
background-color:#808080;
opacity: 0.8;
}
.ng-modal-dialog {
background-color: #fff;
box-shadow: 10px 10px #595554;
border-radius: 4px;
z-index:10000;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.ng-modal-dialog-content {
padding:10px;
text-align: left;
}
.ng-modal-close {
position: absolute;
top: 3px;
right: 5px;
padding: 5px;
cursor: pointer;
font-size: 120%;
display: inline-block;
font-weight: bold;
font-family: 'arial', 'sans-serif';
}

How to get ng-template content from a single html file?

HTML file - directive template
<div class='class1'>
<span ng-show="Edit1">
<script type="text/ng-template" id="editdetails.html">
<div class="modal">
<h3>Update Unit Details</h3>
<input type='text' name='email' value=''>
</div>
</script>
</span>
</div>
<div class='class2'>
<span ng-show="Edit2">
Some content
</span>
</div>
Angular JS code
I am loading this into html file called directive template and then want to get only the ng-template content of editdetails.html how to do that?
var directiveTemplate = null;
var req = new XMLHttpRequest();
req.onload = function () {
directiveTemplate = this.responseText;
};
var url1 = 'directivetemplate.html';
req.open('get', url1, false);
req.send();
$templateCache.put('template.html', directiveTemplate);
$edittemplate=directiveTemplate;
//The below code doesn't get me content inside the editdetails
$templateCache.put('editdetails.html',$edittemplate.filter('#editdetails.html').html());
Obviously you could read more about $templateCache and script documentation at Official AngularJS website. Other option is to try this one.
angular
.module("Example", [])
.controller("ExampleCtrl", ExampleCtrl);
ExampleCtrl.$inject = ['$scope', '$templateCache'];
function ExampleCtrl($scope, $templateCache) {
$scope.getContent = function() {
var script = document.getElementsByTagName("script");
var id = script[2].id;
var htmlContent = $templateCache.get(id);
document.getElementById("display").innerHTML = htmlContent;
};
}
/* Styles go here */
.content {
background-color: green;
color: white;
padding: 10px;
}
.button {
width: 150px;
padding: 10px;
background-color: red;
color: white;
border: 0px white solid;
border-radius: 5px;
}
<!DOCTYPE html>
<html ng-app="Example">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body ng-controller="ExampleCtrl">
<script type="text/ng-template" id="templateId.html">
<p class="content">This is the content of the template</p>
</script>
<p>
<input type="button" class="button" ng-click="getContent()" value="Get Template's Content">
</p>
<div id="display"></div>
</body>
</html>

ng-include Angular JS

I have a main index.html file and in that file, I want to include another .html using ng-include. This is my code:
(I will only upload the relevant code sections, if the whole code is needed, I can edit it)
index.html
<!DOCTYPE html>
<html>
<head>
<!-- include CAPH 3.0.1 default package -->
<link href="lib/caph/3.0.1/caph.min.css" rel="stylesheet" type="text/stylesheet">
<link href="styles/main.css" rel="stylesheet" type="text/stylesheet">
<!-- include jQuery file (you can use AngularJS & jQuery in your environment) -->
<script src="lib/caph/3.0.1/bower_components/jquery/dist/jquery.min.js" type="text/javascript"></script>
<script src="lib/caph/3.0.1/bower_components/angular/angular.min.js" type="text/javascript"></script>
<!-- include the CAPH Package for AngularJS -->
<script src="lib/caph/3.0.1/caph-angular.min.js" type="text/javascript"></script>
</head>
<script>
var myApp = angular.module('myApp', ['caph.focus', 'caph.ui']);
myApp.factory('sharedProperties', function(){
var DEPTH={
MAIN_MENU: 1,
RESTAURANT: 2,
MOVIES: 3,
MOVIE_SELECT: 4
};
var currentDepth;
var focus = function($event) {
$($event.currentTarget).css({
border: '10px solid red'
});
}
var blur = function($event){
$($event.currentTarget).css({
border : '3px solid transparent'
});
}
var select = function($event){
if($event.target.id === "roomservice"){
currentDepth = DEPTH.RESTAURANT;
} else if($event.target.id === "vod"){
currentDepth = DEPTH.MOVIES;
} else if($event.target.id === "back"){
currentDepth = DEPTH.MAIN_MENU;
} else if($event.target.id === "fantasy"){
currentDepth = DEPTH.MOVIE_SELECT;
}
return currentDepth;
}
return{
focus: focus,
blur: blur,
select: select,
currentDepth: currentDepth,
depth: DEPTH
}
});
myApp.controller('myController', function($scope, sharedProperties) {
$scope.currentDepth = sharedProperties.depth.MAIN_MENU;
$scope.focus = function($event){
sharedProperties.focus($event);
}
$scope.blur = function($event){
sharedProperties.blur($event);
}
$scope.select = function($event){
$scope.currentDepth = sharedProperties.select($event);
console.log($scope.currentDepth);
}
$scope.items = [];
for (var i = 0; i < 20; i++) {
$scope.items.push({
text: i+1,
image: 'image/moviepics/' + (i%2 + 1) + '.jpg'
});
}
</script>
<body ng-app="myApp">
<div ng-controller="myController">
<div ng-if="currentDepth === 4">
<h1>Pick a movie</h1>
<div ng-include="'new.html'">
</div>
</div>
</div>
</div>
</body>
</html>
And this is new.html:
<style>
.list{
position: absolute;
width: 600px;
height: 135px;
overflow: hidden;
margin-bottom: 10px;
border: 1px solid transparent;
}
.item{
background: green;
box-sizing: border-box;
border: 3px solid white;
width: 200px;
height: 135px;
}
</style>
<caph-list container-class="list" on-focus-item-view="onFocusItemView($context)" items="item in items">
<div class="item" focusable data-focusable-initial-focus="{{$index===0?true:false}}">
<div class="test" style="width:100%; height:100%; background-size:100% 100%; background: url({{item.image || ''}})"></div>
</div>
</caph-list>
I am getting an ng-areq error with a WARNING of angular loaded more than once. For the full error, please see the attached picture.
I hope my question and code is clear
Any and all help is appreciated. Thank you.
When you include a template, HTML of relevant section of the page needs to be present in it.
In your new.html, you've included everything from the HTML tag which is unnecessary. Remove those and have only the necessary div and other elements.

AngularJS Tabs with UI.Router

I have a single page app with vertical tables to the left. I'm able to to click on each tab and the expected content is showing. The problem I'm having is I'm not able to programmatically change the ng-checked to "true" for the selected tab and "false" for the unselected tab. Because of this the selected tab is always on the first tab in the list of tabs. I've provided all the codes (6 files) to run this app so you can see what im talking about
Index.html
<html ng-app= "mainApp">
<head>
<title>OneilAndK</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" >
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="css/uxcore.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"></script>
<script src="http://angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<script src="routing.js"></script>
<link rel="stylesheet" href="verticalTab.css" rel="stylesheet"/>
</head>
<body>
<div class="tabordion">
<section id="section1">
<input type="radio" name="sections" id="option1" ng-checked = true >
<label ui-sref="About" for="option1">About</label>
<article>
<div ui-view></div>
</article>
</section>
<section id="section2">
<input type="radio" name="sections" id="option2" ng-checked = false >
<label ui-sref="Knowledge" for="option2" >Knowledge</label>
<article>
<div ui-view></div>
</article>
</section>
<section id="section3">
<input type="radio" name="sections" id="option3" ng-checked = false >
<label ui-sref="Contact" for="option3" >Contact</label>
<article>
<div ui-view></div>
</article>
</section>
</div>
</body>
</html>
About.html
<p >This is my about page</p>
Contact.html
<p >This is my Contact page</p>
Knowledge.html
<p >This is my knowledge page</p>
routing.js
var app = angular.module('mainApp', ['ui.router']);
app.config(['$stateProvider','$urlRouterProvider', function($stateProvider,$urlRouterProvider){
$urlRouterProvider.otherwise("Home.html")
$stateProvider
.state('Contact', {url:"/Contact",templateUrl:"Contact.html"})
.state('Knowledge', {url:"/Knowledge",templateUrl:"Knowledge.html"})
.state('About', {url:"/About",templateUrl:"About.html"})
}]);
verticalTab.css
h1 {
color: #333;
font-family: arial, sans-serif;
margin: 1em auto;
width: 80%;
}
.tabordion {
color: #333;
display: block;
font-family: arial, sans-serif;
margin: auto;
position: relative;
width: 80%;
}
.tabordion input[name="sections"] {
left: -9999px;
position: absolute;
top: -9999px;
}
.tabordion section {
display: block;
}
.tabordion section label {
background: #ccc;
border:1px solid #fff;
cursor: pointer;
display: block;
font-size: 1.2em;
font-weight: bold;
padding: 15px 20px;
position: relative;
width: 180px;
z-index:100;
}
.tabordion section article {
display: none;
left: 230px;
min-width: 300px;
padding: 0 0 0 21px;
position: absolute;
top: 0;
}
.tabordion section article:after {
background-color: #ccc;
bottom: 0;
content: "";
display: block;
left:-229px;
position: absolute;
top: 0;
width: 220px;
z-index:1;
}
.tabordion input[name="sections"]:checked + label {
background: #eee;
color: #bbb;
}
.tabordion input[name="sections"]:checked ~ article {
display: block;
}
#media (max-width: 533px) {
h1 {
width: 100%;
}
.tabordion {
width: 100%;
}
.tabordion section label {
font-size: 1em;
width: 160px;
}
.tabordion section article {
left: 200px;
min-width: 270px;
}
.tabordion section article:after {
background-color: #ccc;
bottom: 0;
content: "";
display: block;
left:-199px;
position: absolute;
top: 0;
width: 200px;
}
}
#media (max-width: 768px) {
h1 {
width: 96%;
}
.tabordion {
width: 96%;
}
}
#media (min-width: 1366px) {
h1 {
width: 70%;
}
.tabordion {
width: 70%;
}
}
I would use angular-ui-bootstrap to create tab panels. And for dynamically generating the tab headings you can use stateHelper module.
With stateHelper you can create a configuration object that you can also use inside a ng-repeat to generate the navbar of the tab panel.
The only tricky thing to make it work is the $stateChangeStart listener to calculate the index for the active route. Once the index is found it will be passed to ui-bootstrap via $rootScope.active variable.
Please have a look at the demo below or this jsfiddle.
angular.module('demoApp', ['ui.router', 'ui.bootstrap', 'ui.router.stateHelper'])
.run(['$state', '$rootScope', 'TABS_CONFIG', function($state, $rootScope, TABS_CONFIG) {
// run needed to set the correct tab-index on load
var tabs = TABS_CONFIG.children;
$rootScope.$on('$stateChangeStart', function(e, toState, toParams, fromState, fromParams) {
angular.forEach(tabs, function(item, index) {
if (item.name == toState.name) {
$rootScope.active = index;
}
});
});
}])
.constant('TABS_CONFIG', {
name: 'tabs',
templateUrl: 'tabs.html',
abstract: true,
children: [{
url: '/about',
name: 'about',
template: '<div class="container"><h1>about</h1></div>'
//templateUrl: 'about.html'
}, {
url: '/contact',
name: 'contact',
template: '<div class="container"><h1>contact</h1></div>'
//templateUrl: 'contact.html'
}, {
url: '/knowhow',
name: 'know-how',
template: '<div class="container"><h1>knowhow</h1></div>'
//templateUrl: 'knowhow.html'
},
]
})
.controller('mainController', function($scope, $state, TABS_CONFIG) {
$scope.tabs = TABS_CONFIG.children;
$scope.go = function(tab) {
//$scope.active = $scope.tabs.indexOf(tab);
$state.go(tab.name);
};
})
.config(routes);
function routes($urlRouterProvider, stateHelperProvider, TABS_CONFIG) {
$urlRouterProvider.otherwise('/contact');
stateHelperProvider.state(TABS_CONFIG, {
keepOriginalNames: true
});
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap-tpls.min.js"></script>
<script src="https://cdn.rawgit.com/marklagendijk/ui-router.stateHelper/master/statehelper.js"></script>
<div ng-app="demoApp" ng-controller="mainController">
<div ui-view></div>
<script type="text/ng-template" id="tabs.html">
<uib-tabset active="active">
<uib-tab index="$index" ng-repeat="tab in tabs" ng-click="go(tab)">
<uib-tab-heading>{{tab.name}}</uib-tab-heading>
<div ui-view></div>
</uib-tab>
</uib-tabset>
</script>
</div>

Resources