ng-if Directive: What's the issue here? - javascript

I'm unable to figure out the mistake that's leading to nothing displaying in my div.
HomeController.js (Controller):
app.controller('HomeController', ['$scope', function($scope) {
$scope.icons = [
...
];
$scope.works = [
{
title: 'An Artsy Title for an Artsy Image',
img: 'img/an-artsy-image.png',
orientation: 'portrait',
description: "A artsy description here."
}
];
}]);
index.html (Homepage):
<!DOCTYPE HTML>
<html ng-app="portfolio">
<head>
...
<!-- AngularJS Controller -->
<script src="js/controllers/HomeController.js" type="text/javascript"></script>
<!-- AngularJS Directive -->
<script src="js/directives/introIcon.js" type="text/javascript"></script>
<script src="js/directives/workExpo.js" type="text/javascript"></script>
...
</head>
<body ng-controller="HomeController">
<div class="container-fluid hero">
...
</div>
<div class="container-fluid work-wrapper">
<div class="container work-container">
<div ng-repeat="work in works">
<work-expo info="work"></work-expo>
</div>
</div>
</div>
</body>
</html>
workExpo.js (Directive):
app.directive("workExpo", function() {
return {
restrict: 'E',
scope: 'info',
templateUrl: 'views/directives/workExpo.html'
};
});
workExpo.html (Directive Template):
<div class="row" ng-if="info.orientation === 'landscape'">
<div class="col-lg-12">
<img ng-src="{{ info.img }}" class="img-responsive center-block" />
</div>
<div class="col-lg-12">
<h3>{{ info.title }}</h3>
<p>{{ info.description }}</p>
</div>
</div>
<div class="row" ng-if="info.orientation === 'portrait'">
<div class="col-sm-6">
<img ng-src="{{ info.img }}" class="img-responsive center-block" />
</div>
<div class="col-sm-6">
<h3>{{ info.title }}</h3>
<p>{{ info.description }}</p>
</div>
</div>
It is not clear of what is it that I'm missing in the above code which is leading to my code not displaying at all. To my knowledge there is no problem with the controller or directive in general as the other directive in my code (code not shown) is working just fine.
This is what the code becomes post-compilation as per Chrome's code inspector:
...
<div class="container-fluid work-wrapper">
<div class="container work-container">
<!-- ngRepeat: work in works -->
<div ng-repeat="work in works" class="ng-scope">
<work-expo info="work">
<!-- ngIf: info.orientation === 'landscape' -->
<!-- ngIf: info.orientation === 'portrait' -->
</work-expo>
</div>
<!-- end ngRepeat: work in works -->
</div>
</div>
...
Now clearly, it has not returned any DOM elements under <!-- ngIf: info.orientation === 'portrait' --> which should rather be the case.
Please let me know in case you need any further details. Thanks.

Your scope binding is incorrect in your directive. You need to construct an object with an info property and add 2-way binding of that to the info attribute. Yu can do this as so:
scope: {info:'=info'},
This creates an info property on the scope which evaluates the value of the info attribute, i.e. evaluates work on the parent scope.
Your full directive code therefore becomes:
app.directive("workExpo", function() {
return {
restrict: 'E',
scope: { info: '=info' },
templateUrl: 'views/directives/workExpo.html'
};
});
and everything else can stay the same.
Working JsFiddle

<!-- ngIf: info.orientation === 'landscape' -->
<!-- ngIf: info.orientation === 'portrait' -->
It shows both are not matching so nothing shows
I check your code and it looks good, do one thing to check the value, put following code any where on your page
<pre>
{{ info | json}} - {{ info.orientation | json}}
</pre>

Related

AngularJS unique tab data for each tab

I am pretty close to having this app finished, but have one last hurdle. I am dynamically populating tabs and data via the WordPress Rest API and when I only had 2 tabs it worked wonderfully, but when I added tab 3 and 4 I ran into issues. When I click tabs 2-4 all tabs receive the "active" class instead of just the one that was clicked; thus also all 3 tabs content data also displays.
Here is the code:
var homeApp = angular.module('homeCharacters', ['ngSanitize']);
homeApp.controller('characters', function($scope, $http) {
$scope.myData = {
tab: 0
}; //set default tab
$http.get("http://bigbluecomics.dev/wp-json/posts?type=character").then(function(response) {
$scope.myData.data = response.data;
});
});
homeApp.filter('stripTags', function() {
return function(text) {
return text ? String(text).replace(/<[^>]+>/gm, '') : '';
};
});
<section class="characters" ng-app="homeCharacters" ng-controller="characters as myData">
<div class="char_copy">
<h3>Meet the Characters</h3>
<div class="char_inject" ng-repeat="item in myData.data" ng-show="myData.tab === item.menu_order">
<div class="copy_wrap">
<h3>{{ item.acf.team }}:</h3>
<h2>{{ item.acf.characters_name }} <span>[{{item.acf.real_name}}]</span></h2>
<p class="hero_type">{{ item.acf.hero_type }}</p>
<div class="description" ng-repeat="field in item.acf.character_description">
<p>{{field.description_paragraph}}</p>
</div>
Learn More
</div>
<div class="image_wrap">
<img src="{{ item.acf.homepage_full_image.url }}" />
</div>
</div>
</div>
<div class="char_tabs">
<nav>
<ul ng-init="ch.tab = 0">
<li class="tab" ng-repeat="item in myData.data" ng-class="{'active' : item.menu_order == myData.tab}">
<a href ng-click="myData.tab = item.menu_order">
<img src="{{ item.featured_image.source }}" />
<div class="tab_title_wrap">
<h3>{{ item.acf.characters_name }}</h3>
</div>
</a>
</li>
</ul>
</nav>
</div>
</section>
I would love any ideas! Thanks!
The code seems to work, see Fiddle. What are the values of menu_order? If they are the same for cases 2-4, then that would explain the behaviour.

angularJS - controller stops working when I add ngRoute

So I'm trying to add routes to my angularJS app, and I'm running intro a problem where the main controller for my app stops working if I try to add 'ngRoute' to the app. Additionally, ngRoute is not working.
My code:
app.js (angular logic)
(function() {
angular.module('fccNight', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'results.html'
})
.otherwise({ redirectTo: '/' });
}])
//controllers
.controller('mainController', ['$scope', '$http', function($scope, $http) {
$scope.searchTerm = '';
$scope.data = [];
$scope.loading = false;
$scope.goingNo = [];
$scope.getResults = function() {
if($scope.searchTerm !== '') {
$scope.loading = true;
$scope.data = [];
$http.get('/api/search?term=' + $scope.searchTerm)
.success(function(results) {
$scope.loading = false;
$scope.data = results;
for(var i = 0; i < $scope.data.length; i++) {
$scope.goingNo.push($scope.data[i].going);
}
});
}
}
$scope.addGoing = function(index) {
// check if user is authenticated
if($scope.data[index].going > $scope.goingNo[index]) {
$scope.data[index].going -= 1;
}
else {
$scope.data[index].going += 1;
}
// register in db
}
}])
})();
index.html's body:
<body ng-controller="mainController" id="mainController">
<!-- CONTENT -->
<div class="container">
<div class="row text-center">
<div class="col-xs-12 main">
<h1>Where are you going tonight?</h1>
<p>Find nearby pubs and RSVP ahead of time.</p>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-8 col-lg-offset-2">
<form>
<div class="input-group">
<input id="inputSearch" ng-model="searchTerm" type="text" class="form-control" placeholder="Where are you?" autocomplete='off'>
<span id="goBtn" class="input-group-btn">
<a ng-click="getResults()" class="btn btn-default">Go</a>
</span>
</div>
</form>
</div>
</div>
<!-- LOADING -->
<div class="row loading hidden" ng-show="loading">
<div class="col-xs-12">
<div class="loader"></div>
</div>
</div>
<div class="text-center">Controller is working if search term is displayed: {{ searchTerm }}</div>
<!-- TEMPLATE -->
<div ng-view></div>
</div>
<!-- footer -->
<footer class="row-footer">
<div class="container">
<div class="row">
<div class="col-xs-12 text-center">
<a href="https://github.com/otmeek/fcc-night">
<i class="fa fa-github"></i>
</a> |
<a href="https://www.freecodecamp.com">
<i class="fa fa-fire"></i>
</a> | built using the Yelp API
</div>
</div>
</div>
</footer>
<!-- =====================SCRIPTS===================== -->
<!-- jQuery -->
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<!-- Bootstrap -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<!-- AngularJS -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-route.js"></script>
<!-- custom scripts -->
<script src="js/app.js"></script>
<script src="js/scripts.js"></script>
</body>
results.html (the template I want to load in on '/' route)
<p>Results are loading</p>
<div class="row result" ng-repeat="result in data">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-8 col-lg-offset-2 result">
<div class="row">
<!-- image -->
<div class="col-xs-3 col-sm-2">
<div class="image">
<img ng-src="{{ result.image || 'img/noimage.jpg' }}">
</div>
<div ng-click="addGoing($index)" class="going text-center">
{{ result.going || 0 }} going
</div>
</div>
<!-- text -->
<div class="col-xs-9 col-sm-10">
<h4><a ng-href="{{ result.url || '#' }}">{{ result.name }}</a>
<small>{{ 'Rating: ' + result.rating || 'No rating available' }}</small></h4>
<p>{{ result.text || 'No reviews for this establishment.' }}</p>
</div>
</div>
</div>
</div>
As I said, if I remove all the routing logic from app.js and ng-view from index.html and just add in results.html, the app is running fine, controller is loading properly and everything is ok. But upon adding 'ngRoute' to the app, the results template doesn't load and I can't access any mainController variables or logic from index.html.
If anyone knows what I'm doing wrong please let me know. Thanks!
Edit: I just noticed the cdn for angular-route.js is not working. I can't find a download link for this library in the official site and I don't have bower so I have no idea where to get this file.
There is an error for angular-route.js
https://ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-route.js
its adress is wrong. There is no version for it. Write your version insteadof X.Y.Z
suchas https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-route.js
You need to change X.Y.Z by any specific version like 1.4.8 in your index.html page for angular route.
So you should use
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
instead of
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-route.js"></script>

Trying to insert elements into view (HTML) from controller ($scope) in AngularJS

I want to insert a dictionary (array of objects) into the view in my project . The view is called "product", the controller is called "ProductCtrl".
The output I want to show is just static data. Below is my code:
/*
* "product" module.
*/
'use strict';
angular.module('myApp.products', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/products', {
templateUrl: 'products/products.html',
controller: 'ProductCtrl'
});
}])
.controller('ProductCtrl', [function($scope) {
//the problem is that I wanna insert those elements using angular and I cannot.
$scope.productos=[
{titulo:"1111", descripcion:"!", precio: 25.95, imagen: "camisetas2.png"},
{titulo:"2222", descripcion:"!A", precio: 25.95, imagen: "camisetas3.png"}
];
}]);
<!--("Producto" View-HTML)-->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="row" ng-controller="ProductCtrl">
<div class="col-md-12">
<div class="row" ng-repeat="producto in productos"> <!-- Basic for loop -->
<div class="col-md-12">
<!-- Inicio del contenido; se exponen la empresa y sus servicios (9/4 grid system) -->
<h2>{{ producto.titulo }}</h2>
<div class="row">
<div class="col-md-2">
<img width="120" height="120" alt="mundo camis" src="img/mundo.jpg" class="img-circle">
</div>
<div class="col-md-10">
<div class="caption">
<h3> {{ producto.titulo }} </h3>
<p> {{ producto.descripcion }} </p>
<p> <a class="btn-primary" href="#">Ver más</a> </p>
</div>
</div>
</div>
</div>
</div>
<br /> <br />
</div>
</div>
</div>
You had a few mistakes, and the most important - not setting the ng-app attribute. I made a simple example for you to use. Code below, link here: http://codepen.io/anon/pen/GoqWyM.
I advise learning Angular from the following tutorial: http://campus.codeschool.com/courses/shaping-up-with-angular-js/ .
The answer:
/*
* "product" module.
*/
'use strict';
var app = angular.module('Products', []);
app.controller('Producto', [function() {
this.productos=[
{titulo:"1111", descripcion:"!", precio: 25.95, imagen: "camisetas2.png"},
{titulo:"2222", descripcion:"!A", precio: 25.95, imagen: "camisetas3.png"}
];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Products" class="row" ng-controller="Producto as ProdCtrl">
<div ng-repeat="producto in ProdCtrl.productos">
{{ producto.titulo }}
</div>
</div>

Books Won't Display for Reader App Exercise

I'm trying to get books to display based on the assignment above but can't figure out what is wrong for the life of me.
I built the service and modified the controller and view pages to the point where I believe they should display the books in the view, but I'm just seeing a blank page.
I feel like I am probably not retrieving the data properly and accessing it in the view/html.
Any ideas? Link to jsFiddle.
Index.html
<body ng-app="ReaderApp">
<div class="header">
<div class="container">
Reader
</div>
</div>
<div class="main">
<div class="container">
<div ng-view></div>
</div>
</div>
<!-- Modules -->
<script src="js/app.js"></script>
<!-- Controllers -->
<script src="js/controllers/BookshelfController.js"></script>
<script src="js/controllers/BookController.js"></script>
<script src="js/controllers/ChapterController.js"></script>
<!-- Services -->
<script src="js/services/books.js"></script>
</body>
js/apps.js
var app = angular.module('ReaderApp', ['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/books', {
controller: 'BookshelfController',
templateUrl: 'views/bookshelf.html'
})
.otherwise({
redirecTo: '/books'
});
});
js/services/books.js
app.factory('books', ['$http', function($http) {
return $http.get('https://s3.amazonaws.com/codecademy-content/courses/ltp4/books-api/books.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
js/controllers/BookshelfController
app.controller('BookshelfController', ['$scope', 'books', function($scope, books) {
books.success(function(data) {
$scope.myBooks = data;
});
}]);
js/views/bookshelf.html
<div class="bookshelf row">
<!--
TODO: Loop through myBooks and display each one with this HTML
<div class="book col-md-3">
<a href="#/books/{{$index}}">
TODO: Add the book's cover here
<h3 class="title"> </h3>
<p class="author"> </p>
</a>
</div>
-->
<div class="book col-md-3" ng-repeat="book in myBooks">
<a href="#/books/{{$index}}">
<img ng-src="{{ book.cover }}">
<h3 class="title">{{ book.title }}</h3>
<p class="author">by {{ book.author }}</p>
</a>
</div>
</div>
I think I had the same trouble and my problem was in the router. Try adding array brackets ( [ ] ) and the '$routeProvider' string in your config method (app.js) like this:
app.config(['$routeProvider', function($routeProvider) {
// Normal router stuff goes here
}]);
Coming from Ember, the syntax is a little weird so I've been using this tutorial as reference when I get stuck.

Ng-repeat, first item with different directive

I got the following code:
<div ng-repeat="i in placeholders" square class="set-holder {{i.class}}" droppable="{{i.type}}"></div>
How I make the first item has the directive bigsquare, while the others have just square.
I've tried:
<div ng-repeat="i in placeholders" {{= $first ? 'big' : ''}}square class="set-holder {{i.class}}" droppable="{{i.type}}"></div>
but sadly I the result is:
<div ng-repeat="i in placeholders" {{= $first ? 'big' : ''}}square class="set-holder test" droppable="3"></div>
a.k.a. the binding don't get compiled.
You can use ng-repeat-start and ng-repeat-end as follows:
angular.module('example', [])
.controller('ctrl', function Ctrl($scope) {
$scope.items = [1, 2, 3];
})
.directive('big', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.css('font-size', '30px');
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="example" ng-controller="ctrl">
<div ng-repeat-start="item in items" ng-if="$first" big>
big item {{item}}
</div>
<div ng-repeat-end ng-if="!$first">
item {{item}}
</div>
</div>
The documentation can be found under ng-repeat.
See this fiddle http://jsfiddle.net/nicolasmoise/xLfmK/2/.
You can create one directive to which you pass a condition. Depending on that condition it will either display the square or the big-square as such.
<div ng-repeat="repeat in repeater" condition="$first" square></div>
Note
If you don't want to alter the directives you're already made, you can always have square be a master directive that calls the other two.
If you don't mind using another <div> inside of your <li>, you should be able to get away with doing conditional blocks of <div> using ng-if="$index == ??".
Maybe something like this:
<div ng-repeat="i in placeholders">
<div bigsquare class="set-holder {{i.class}}" droppable="{{i.type}}" ng-if="$index == 0">
...
</div>
<div mediumsquare class="set-holder {{i.class}}" droppable="{{i.type}}" ng-if="$index == 1">
...
</div>
<div square class="set-holder {{i.class}}" droppable="{{i.type}}" ng-if="$index > 1">
...
</div>
</div>
It's a little more verbose, but it nicely separates out the templates so that you can have them pretty independent of each other.
<!-- Here is a code sample which I used in one of my angularjs ionic apps. -->
<!-- Regular ng-repeat -->
<!-- ng-if="$first" to determine <input focus-input> or not -->
<ion-item class="item item-input item-stacked-label" ng-repeat="input in template.inputs">
<label class="input-label bh-dark" for="{{input.id}}">{{input.title}}</label>
<div class="clearfix">
<div class="bh-left">
<input ng-if="$first" focus-input id="{{input.id}}" type="{{input.type}}" placeholder="{{input.choices[0]}}" ng-model="input.answer">
<input ng-if="!$first" id="{{input.id}}" type="{{input.type}}" placeholder="{{input.choices[0]}}" ng-model="input.answer">
</div>
<div class="bh-right">
<i class="icon ion-ios-close-empty bh-icon-clear" ng-click="clearField(input.id)" ng-show="input.answer"></i>
</div>
</div>
</ion-item>

Categories

Resources