Pairing angular js directives with jQuery - javascript

What's the best way to manipulate a template of a ng directive with jQuery? When I try to animate or toggle classes that are inside a directive's template, nothing happens. For instance:
HTML:
<div class="projects">
<h2>Projects</h2>
<div class="row">
<div class="col-lg-12">
<div class="row" ng-controller="ProjectsController">
<div class="project-boxes" ng-repeat="project in projects">
<projects-info info="project"></projects-info>
</div>
</div>
</div>
</div>
</div>
Directive's template:
<div class="prjcontainer">
<img class="boximg" ng-src="{{ info.img }}">
<p> {{ info.description }}</p>
</div>
Script
$(document).ready(function(){
$('.boximg').hover(
function() {
$(this).stop().animate({
width: '300px',
height: '300px'}, 500);
},
function() {
$(this).stop().animate({
width: '100px',
height: '100px' }, 500);
});
Directive code:
app.directive('projectsInfo', function() {
return {
restrict: 'E',
scope: {
info: '='
},
templateUrl: 'components/projects/projects-template/projectsInfo.html'
};
});
My main goal is to have a info viewer like how on the Netflix site when you hover over a show, the picture gets bigger and text displays on the inside.
Thanks!

Related

ui.bootstrap.carousel is not appearing

For some reason I am not able to see, my Carousel will not appear. My project requires slightly different implementation than what is defined here. It should work fine though, I've outlined the details below.
Clicking my button toggles openModal, where I specify my scope as modal:
openModal() {
var _this = this;
this.$uibModal.open({
animation: true,
templateUrl: 'components/directives/modals/Modal/Modal.html',
controller: 'ModalController',
controllerAs: 'modal',
size: 'lg',
}
});
}
In this controller I declare some variables in the constructor:
//Carousel Variables
this.active = 0;
this.currIndex = 0;
this.slides = [];
this.addSlide();
This calls my controller function addSlide:
addSlide() {
for (var i=0;i<4;i++) {
this.slides.push({
image: 'https://unsplash.it/600/300',
text: ['Getting Started', 'Awesome photograph', 'That is so cool', 'I love that'][this.slides.length % 4],
id: this.currIndex++
});
}};
HTML
<div style="height: 200px;">
<div uib-carousel active="modal.active" interval="0" no-wrap="false">
<div uib-slide ng-repeat="slide in modal.slides" index="modal.slide.id">
<img ng-src="{{modal.slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{modal.slides.id}}</h4>
<p>{{modal.slides.text}}</p>
</div>
</div>
</div>
</div>
Change your markup from...
<div uib-slide ng-repeat="slide in modal.slides" index="modal.slide.id">
<img ng-src="{{modal.slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{modal.slides.id}}</h4>
<p>{{modal.slides.text}}</p>
</div>
</div>
...to this...
<div uib-slide ng-repeat="slide in modal.slides" index="slide.id">
<img ng-src="{{slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{slide.id}}</h4>
<p>{{slide.text}}</p>
</div>
</div>">
By including the modal. in there you are referencing a non-existent slide property on the controller when what you really want is to reference the slide object in your ng-repeat. (You also had slides in a couple places where I think you meant slide).

materialbox Materializecss works only after typing initialization jQuery in console

I have used '.materialboxed' in my webpage, but the initialization in script doesn't work, I have to manually type $('.materialboxed').materialbox(); in console for it to work.
Html (ui-view in angular route)
<div class="row">
<div class="card-panel col l12" style="height: 750px;">
<img class="col l5 materialboxed" height="500px" id="poster"
ng-src="https://image.tmdb.org/t/p/original{{poster_path}}"/>
<div class="col l7">
<div class="row">
<a class="col l10" style="float:left;text-align: left;" ng-href="{{homepage}}">
<h3 class="title" ng-bind="original_title"></h3>
</a>
<a ng-href="http://www.imdb.com/title/{{imdb_link}}"
style="float:right;text-align: right; margin-top: 29px;"
class="imdb-link col l2" title="IMDb"><i class="icon-imdb"></i></a>
</div>
<div class="row"><p ng-bind="overview"></p>
<span class="right" ng-bind="release_date"></span>
<h5>Genres</h5>
<p ng-bind="genre"></p>
<h5>Production Companies</h5>
<p ng-bind="names">
</p>
<h5>Voting</h5>
<p ng-bind="vote_average"></p></div>
</div>
</div>
</div>
See the in 3rd line.
index.html
//rest code
<main ui-view></main>
</div>
<script src="js/angular_min.js"></script>
<script src="js/angular-touch.min.js"></script>
<script src="js/angular-ui-router.min.js"></script>
<script src="js/angucomplete-alt.js"></script>
<script src="appRoute.js"></script>
<script src="controller/MovieController.js"></script>
<script src="controller/LoginController.js"></script>
<script src="controller/RegisterController.js"></script>
<script src="controller/TvController.js"></script>
<script src="controller/LoggedInController.js"></script>
<script src="controller/TopMovieController.js"></script>
<script src="app-services/DetailsService.js"></script>
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/materialize.min.js"></script>
<script>
$(document).ready(function () {
$('.materialboxed').materialbox();
$('.button-collapse').sideNav({
menuWidth: 300,
edge: 'left',
closeOnClick: true
}
);
$('.modal-trigger').leanModal();
$("#movie").click(function () {
window.location.href = window.location.pathname + "#/movie";
});
$("#tv").click(function () {
window.location.href = window.location.pathname + "#/tv";
});
});
</script>
</body>
Even after initializing the materialboxed, it doesn't work. It works only after typing $('.materialboxed').materialbox(); in console manually.
Help me figure this out. Thanks
You shouldn't use $(document).ready in Angular. In fact you should try to use as little jQuery as possible, but if you need to, then you should create a directive that allows you to initialize the function after they render.
var app = angular.module('myApp');
app.directive('onLastRepeat', function() {
return function(scope, element, attrs) {
if (scope.$last)
setTimeout(function() {
scope.$emit('onRepeatLast', element, attrs);
}, 1);
};
});
app.controller('MoviesController', function($scope) {
$scope.$on('onRepeatLast', function(scope, element, attrs) {
$('.materialboxed').materialbox();
});
}
Now you can apply this to your HTML:
<ul>
<!-- this is just an example with the added directive -->
<li ng-repeat="movie in movies" on-last-repeat>
<img ng-src="{{imageObjectHere}}" class="materialboxed">
</li>
</ul>
Since you added this new directive in there, the $('.materialboxed').materialbox(); should fire after the repeat is done

Change background image on hover with AngularJS

I have a scope of 's with their background images, but I can't figure out how to make them change. I tried several variants, but none of them has passed. Here's the code:
<div ng-controller="mainController" class="main">
<div ng-repeat="land in lands" class="col-md-9" ng-style="{ 'background-image': 'url({{ land.cover }})'}">
<p>{{ land.name }}</p>
</div>
</div>
Javascript:
app.controller('mainController', ['$scope', function($scope) {
$scope.lands = [
{
cover: 'img/norway.jpg',
cover1: 'img/norway1.jpg',
name: 'Norway'
},
{
cover: 'img/sweden.jpg',
cover1: 'img/sweden1.jpg',
name: 'Sweden'
},
{
cover: 'img/denmark.jpg',
name: 'Danmark'
},
{
cover: 'img/iceland.jpg',
name: 'Iceland',
},
{
cover: 'img/finland.jpg',
name: 'Finland'
},
{
cover: 'img/estonia.jpg',
name: 'Estonia'
}
];
}]);
You can't use interpolation tags in the expression context. Should be:
<div ng-controller="mainController" class="main">
<div ng-repeat="land in lands" class="col-md-9"
ng-init="coverImage = land.cover"
ng-mouseover="coverImage = land.cover"
ng-mouseout="coverImage = land.cover1"
ng-style="{ 'background-image': 'url(' + coverImage + ')' }">
<p>{{ land.name }}</p>
</div>
</div>
Since you're trying to respond to the DOM, the angular way of doing this would be to create a directive.
Working code is available here. The summary of the solution is this:
Your DOM will change to this:
<div ng-controller="MainController as ctrl">
<div ng-repeat="land in ctrl.lands" hover-bg-change default-bg="land.cover" hover-bg="land.cover1" class='tile'>
<p>{{ land.name }}</p>
</div>
</div>
The directive will look like this:
app.directive('hoverBgChange', ['$parse', function ($parse)
{
return {
restrict: 'A',
link: function (scope, $el, attrs)
{
var defaultBg = $parse(attrs.defaultBg)(scope);
var hoverBg = $parse(attrs.hoverBg)(scope);
$el.css('background-image', 'url('+defaultBg+')');
$el.on('mouseover', function ()
{
$el.css('background-image', 'url('+hoverBg+')');
})
.on('mouseout', function ()
{
$el.css('background-image', 'url('+defaultBg+')');
});
}
}
}])
You can't make it work in one go.
My solution would be
define css as
.hover-out{
background-image: url('img/norway.jpg');
}
.hover-in{
background-image: url('img/norway1.jpg');
}
In markup
<div ng-controller="mainController" class="main">
<div ng-repeat="land in lands" class="col-md-9" ng-class="{'hover-out':hoverOut[$index], 'hover-in':!hoverOut[$index]}" ng-mouseover="hoverOut[$index] = false" ng-mouseleave="hoverOut[$index] = true">
<p>{{ land.name }}</p>
</div>
</div>

Angular directive attributes not being passed into scope

my angular directives' arguments aren't getting passed into the scope:
app.directive('sectionLeft', function() {
return {
restrict:'E',
scope: {
sectionContent: '=',
sectionImg: '='
},
templateUrl: 'partials/section_left.html'
};
});
app.directive('sectionRight', function() {
return {
restrict:'E',
scope: {
sectionContent: '=',
sectionImg: '='
},
templateUrl: 'partials/section_right.html'
};
});
They're called from here:
<div ng-repeat="content in data.home">
<section-left ng-if="$even" sectionContent="{{content}}" sectionImg="http://placehold.it/700x450"></div>
<section-right ng-if="$odd" sectionContent="{{content}}" sectionImg="http://placehold.it/700x450"></div>
</div>
and look like this:
<div class="section">
<div class="container">
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-6">
{{sectionContent}}
</div>
<div class="col-lg-6 col-md-6 col-sm-6">
<img class="img-responsive" src="{{sectionImg}}">
</div>
</div>
</div>
</div>
The result is just a blank space with no content, but I can see the attributes getting set on the directive element. What's going on?
Thanks in advance!
Need to remove the {{}} to pass scope variables to directive using = in isolated scope.
section-content="content"
This will imply that the 2 way binding will be to a parent scope variable named content

angular.js two directives, second one does not execute

I have two directives defined in an angular.js module. The HTML element that is declared first executes its directive, but the second HTML element that uses the other directive does not execute it.
Given this HTML:
<div ng-app="myApp">
<div ng-controller="PlayersCtrl">
<div primary text="{{primaryText}}"/>
<div secondary text="{{secondaryText}}"/>
</div>
</div>
and this angular.js code:
var myApp = angular.module('myApp', []);
function PlayersCtrl($scope) {
$scope.primaryText = "Players";
$scope.secondaryText = "the best player list";
}
myApp.directive('primary', function(){
return {
scope: {
text: '#'
},
template: '<h1>{{text}}</h1>',
link: function(scope, element, attrs){
console.log('primary directive');
}
};
});
myApp.directive('secondary', function(){
return {
scope: {
text: '#'
},
template: '<h3>{{text}}</h3>',
link: function(scope, element, attrs){
console.log('secondary directive');
}
};
});
The resulting HTML is only the "primary" directive, and the "secondary" directive does not render:
<div ng-app="myApp" class="ng-scope">
<div ng-controller="PlayersCtrl" class="ng-scope">
<div primary="" text="Players" class="ng-isolate-scope ng-scope">
<h1 class="ng-binding">Players</h1>
</div>
</div>
</div>
The console output verifies this as well, as only the "primary directive" text is output.
Then if I switch the order of the primary and secondary elements, the secondary directive is executed and the primary directive is not:
<!-- reversed elements -->
<div secondary text="{{secondaryText}}"/>
<div primary text="{{primaryText}}"/>
<!-- renders this HTML (secondary, no primary) -->
<div ng-app="myApp" class="ng-scope">
<div ng-controller="PlayersCtrl" class="ng-scope">
<div secondary="" text="the best player list" class="ng-isolate-scope ng-scope">
<h3 class="ng-binding">the best player list</h3>
</div>
</div>
</div>
Why is this? What am I doing wrong?
div's are not void elements and require a closing tag.
<div ng-app="myApp">
<div ng-controller="PlayersCtrl">
<div primary text="{{primaryText}}"></div>
<div secondary text="{{secondaryText}}"></div>
</div>
</div>
Example

Categories