Change background image on hover with AngularJS - javascript

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>

Related

Angular hide an element in ng-repeat on click

I have articles listed on a page in my app, where I have an iframe and overlay over that iframe. I want to have it that when a user clicks on an iframe overlay, that the title from that article gets hidden. Not sure how to achieve that in ng-repeat. This the code, where as of now, on a click event titles of all articles get hidden.
<ion-item ng-repeat="article in articles" class="item-light">
<div class="article">
<a ng-show="article.external_media.length == 0 || article.external_media.url == ''" href="#/main/article/{{article.id}}" nav-direction="forward" class="article-image-link">
<img src="{{ fileServer }}/imagecache/cover/{{article.cover_image}}">
<h1>{{ article.title.split(' ', 7).join(' ') }}</h1>
</a>
<div class="iframe" ng-show="article.external_media.length > 0 && article.external_media.url != ''">
<iframe ng-src="{{article.external_media[0].url | safeUrl }} "></iframe>
<div class="article-image-link">
<h1 ng-hide="videoPlaying">{{ article.title.split(' ', 7).join(' ') }}</h1>
</div>
<div class="iframe-overlay" ng-click="playVideo()"></div>
</div>
</div>
</ion-item>
Controller:
$scope.playVideo = function(videoSrc) {
$scope.videoPlaying = true;
$scope.videoSrc = videoSrc + "&autoplay=1";
};
you can also use $index for this purpose.
controller
app.controller('someController',function($scope){
$scope.videoPlaying = [];
$scope.playVideo = function(videoSrc,index) {
$scope.videoPlaying[index] = true;
$scope.videoSrc = videoSrc + "&autoplay=1";
};
$scope.stopVideo = function(videoSrc,index) {
$scope.videoPlaying[index] = false;
$scope.videoSrc = videoSrc + "&autoplay=1";
};
})
HTML
i am changing only two lines rest are same as it is
<h1 ng-hide="videoPlaying[$index]">{{ article.title.split(' ', 7).join(' ') }}</h1>
<div class="iframe-overlay" ng-click="playVideo($index)"></div>
I've created a JSFIDDLE (basic) to give you a head start on what you are trying to do.
VIEW
<div ng-app="app">
<div ng-controller="helloCnt">
<div ng-repeat='item in data'>
<span ng-if="item.hide === undefined || !item.hide">{{item.name}}</span>
<div ng-if="!item.hide" ng-click="playVideo(item)">
HIDE
</div>
<div ng-if="item.hide" ng-click="stopVideo(item)">
SHOW
</div>
<br/>
</div>
</div>
</div>
CONTROLLER
var app = angular.module('app', [])
app.controller('helloCnt', function($scope) {
$scope.data = [{
'name': 'test'
}, {
'name': 'in'
}, {
'name': 'dummy'
}, {
'name': 'data'
}]
$scope.playVideo = function(item, videoSrc) {
// other code
item.hide = true;
};
$scope.stopVideo = function(item, videoSrc) {
// other code
item.hide = false;
};
})
SEE JSFIDDLE

Toggle other elements inside ng-repeat on ng-click

I'm trying to apply class by using ng-class and ng-click and this working fine for selected element, but how can I toggle this class in the other elements?
Improved description:
Current behaviour:
Click on elelement, class applied.
Clik on the other element, this element also class applied.
Desired behaviour:
Click on element, class applied.
Other element - class removed.
<div ng-repeat="element in ngModel | orderBy:'Field_Order'" class='elementForm' ng-hide="element.IsDeleted">
<div layout="row" style="width:100%" class="container" ng-mouseover="hovering=true" ng-mouseleave="hovering=false" flex ng-click="selected = !selected">
<div class="hover-space" ng-class="{'hoveredFormElement':hovering, 'selected':selected}" flex="2" ></div>
....
</div>
</div>
The problem is, selected is inside an isolated scope which is not shared by other items.
One easy solution using index is
var app = angular.module('my-app', [], function() {})
app.controller('AppController', function($scope) {
$scope.selected = -1;
$scope.ngModel = [{
i: 1
}, {
i: 2
}, {
i: 3
}, {
i: 4
}];
})
.hoveredFormElement {
color: green;
}
.selected {
background-color: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="my-app">
<div ng-controller="AppController">
{{selected}}
<div ng-repeat="element in ngModel | orderBy:'Field_Order'" class='elementForm' ng-hide="element.IsDeleted">
<div layout="row" style="width:100%" class="container" ng-mouseover="hovering=true" ng-mouseleave="hovering=false" flex ng-click="$parent.selected = $parent.selected == $index ? -1 : $index">
<div class="hover-space" ng-class="{'hoveredFormElement':hovering, 'selected':selected == $index}" flex="2">{{element}}</div>
</div>
</div>
</div>
</div>
Maintain flag in controller scope and use it over ng-class
$scope.selected = { index: undefined };
Markup
<div ng-repeat="element in ngModel | orderBy:'Field_Order'" class='elementForm' ng-hide="element.IsDeleted">
<div layout="row" style="width:100%" class="container"
ng-mouseover="hovering = true"
ng-mouseleave="hovering = false"
flex ng-click="selected.index = !selected">
<div class="hover-space"
ng-class="{'hoveredFormElement':hovering , 'selected':selected.index }" flex="2" ></div>
....
</div>
</div>

Pairing angular js directives with jQuery

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!

Trouble with ng-repeat

I'm trying to get to grips with AngularJS and had this working to echo individual things from a controller, but when I tried to incorporate a loop with ng-repeat all I get is {{tasks.title}} flashing onscreen for a second, then a blank empty div.
Any examples I've looked up seem a little different and I've tried a few ways, can anyone see where I'm going wrong?
Controller:
app.controller('MainController', ['$scope', function($scope) {
$scope.tasklist = {
tasks: [{
title: 'Wash Dog'
}, {
title: 'Email Joe'
}]};
}
]);
HTML:
<section class="panel">
<div ng-controller="MainController">
<div class="thumbnail" ng-repeat="tasks in tasklist">
<p>{{ tasks.title }}</p>
</div>
</div>
</section>
You are accessing the property tasklist not the actual tasks. It should be tasklist.tasks
<section class="panel">
<div ng-controller="MainController">
<div class="thumbnail" ng-repeat="tasks in tasklist.tasks">
<p>{{ tasks.title }}</p>
</div>
</div>
</section>
Another way would be to remove the tasks property:
app.controller('MainController', ['$scope', function($scope) {
$scope.tasklist = [
{
title: 'Wash Dog'
},
{
title: 'Email Joe'
}
];
}]);

angular: calling/triigering directive method from parent scope

in my app I defined a directive which implement a simple slider with a next/prev/goto methods.
The slider then is within an html snipet managed by another controller.
The problem is that the last slide contains a form, so if the submit is ok than I would like to go to the next slide.
In old javascript I would have passed a callback to the submit method in order to apply that callback.
I made the same thing. Is this the best / angular style way to do it?
Javascript (I omitted some detail):
.directive("sfCarousel", function() {
return {
scope: true,
restrict: 'A',
controller: function($scope) {
var slides = $scope.slides = [];
var currentIndex = $scope.currentIndex = -1;
$scope.next = function() {
//mynextfunction...
}
},
link: function(scope, element, attrs) {
console.log("sf-carousel");
}
}
})
.directive("sfCarouselItem", function() {
return {
scope: true,
require: '^sfCarousel',
link: function(scope, element, attrs, sfCarouselController) {
console.log("sf-carousel-item");
sfCarouselController.addSlide(scope);
}
}
})
.controller("mycontroller", ['$scope', function($scope) {
$scope.submit = function (callback) {
//if submit is ok then
callback.apply(null, []);
}
}])
HTML:
<div sf-carousel >
<div sf-carousel-item ng-class="{'active':active}" >
<div>my first slide</div>
<div sf-label="get-started.submit" ng-click="next()" ></div>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<form>
<!--here my form-->
<button type="submit" ng-click="submit(next)">submit and go</button>
</form>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<div>my last slide</div>
<!--other things-->
</div>
</div>
You can pass the function that you what to run on the parent controller.
// directive sfCarousel
return {
transclude: true,
template: '<div class="sf-carousel" ng-transclude></div>',
// ...
};
// directive sfCarouselItem
return {
transclude: true,
scope: {
func: '&',
// ...
},
template: '<div class="sf-carousel-item" ng-transclude></div>',
}
// controller html
<div sf-carousel >
<div sf-carousel-item ng-class="{'active':active}" >
<div>my first slide</div>
<div sf-label="get-started.submit" ng-click="next()" ></div>
</div>
<div sf-carousel-item func="next()" ng-class="{'active':active}" >
<form>
<!--here my form-->
<button type="submit" ng-click="func({})">submit and go</button>
</form>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<div>my last slide</div>
<!--other things-->
</div>
</div>

Categories