I'm building a website using angular for a tabbed table of links and I can't get the templated section to show up at all. Not sure where the issue lies, but I believe everything is set up correctly and the files are all on a hosted drive that I've used to properly test javascript plenty of times. Is there anything wrong with the angular or HTML? I've just included the pertinent bits.
HTML:
<html lang="en" ng-app="operations">
<head>
...
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="base_styles.css" type="text/css">
<script type="text/javascript" language="javascript" src="Operations.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body ng-controller="OperationsController as ops">
<div id="header">
<h1>Operations</h1>
<category-tabs></category-tabs>
</body>
</html>
Angular JS:
(function() {
var operationsApp = angular.module('operations', []);
operationsApp.controller('OperationsController', function() {
var operations = this;
operations.categories = [];
});
OperationsController.directive("categoryTabs", function() {
return {
restrict: "E",
templateUrl: "category-tabs.html"
});
})();
Template HTML:
<section>
<ul class = "nav nav-pills">
<li ng-class = "{ active : tab.isSet(1) }">
<a href ng-click="tab.setTab(1)">Popular Tools</a>
</li>
...
</ul>
</section>
Unless you're doing something really clever that I haven't seen before, I think your problem lies in this line:
OperationsController.directive("categoryTabs", function() { });
You seem to be calling .directive on a Controller, which is odd. You are also missing a closing } on the directive definition object. Are you looking at the javascript console? Errors like this should show up.
.directive() is a method of an angular module, so you should use:
operationsApp.directive("categoryTabs", function() { });
P.S. you can make everything a bit neater an more readable if you chain everything off the initial .module(). This is how your code would look:
angular.module('operations', [])
.controller('OperationsController', function() {
var operations = this;
operations.categories = [];
})
.directive("categoryTabs", function() {
return {
restrict: "E",
templateUrl: "category-tabs.html"
}
});
Related
I am just getting started with AngularJs and I'm making a simple site navigation app that queries an API for values. Currently I'm trying to make an accordion sidebar applet (is that the correct term for a child app of a parent app?) that loads the primary sections, then lists the categories within when the section headers are clicked.
Well I got it to work without throwing an error (yay!) but if I apply the css, then the accordion becomes timid and bashful, only revealing whats inside for less than a second before hiding the contents again. And a lot of times I have to click on the header twice before something happens.
I'm guessing its a problem with Bootstrap because as I mentioned, It's not like that if I remove the css and just have raw html output. Here's my code:
index.html
<!DOCTYPE html>
<html ng-app="navApp" ng-strict-di>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css" />
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>
<![endif]-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-resource.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-route.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-animate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js" type="text/javascript"></script>
<script src="~/Areas/AngularTest/scripts/app.js"></script>
</head>
<body ng-cloak>
<div ng-controller="menuController">
<div ng-include src="'templates/sidebar.html'"></div>
</div>
</body>
</html>
Using Grunt to combine my js files into one app.js so here are the separate pieces.
scripts/controllers/navController.js
var navApp = angular.module('navApp', [
'ngResource',
'ui.bootstrap',
'ngAnimate'
]);
navApp.controller('menuController', [
'$scope',
'navSectionList',
'navGetCategories',
function ($scope, navSectionList, navGetCategories) {
$scope.navSectionList = navSectionList.query();
$scope.getSectionID = function (event) {
var sectionID = event.currentTarget.attributes["data-id"].value;
$scope.sectionID = sectionID;
$scope.navGetCategories = navGetCategories
.getResource(sectionID)
.query();
};
}
],
function ($scope) {
$scope.oneAtATime = true;
$scope.status = {
isFirstOpen: true,
isFirstDisabled: false
};
}
);
scripts/services/navService.js
navApp.factory('navSectionList', [
'$resource', function ($resource) {
return $resource('/api/navigation/section/list', {}, {
query: { method: 'GET', params: {}, isArray: true }
});
}
]);
navApp.factory('navGetCategories', ['$resource', function ($resource) {
var service = {
getResource: function (sectionID) {
return $resource('/api/navigation/category/' + sectionID, {}, {
query: { method: 'GET', params: {}, isArray: true }
});
}
};
return service;
}]);
templates/sidebar.html
<div class="sidebar">
<uib-accordion close-others="oneAtATime">
<div uib-accordion-group class="panel-default" heading="Products" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
<ul>
<li>New Arrivals</li>
<li>On Sale</li>
</ul>
</div>
<div uib-accordion-group class="panel-default" heading="{{section.name}}" ng-click="getSectionID($event)" ng-repeat="section in navSectionList" data-id="{{section.id}}">
<ul ng-repeat="categories in navGetCategories">
<li ng-show="categories.pid == section.id">
{{categories.name}}
</li>
</ul>
</div>
</uib-accordion>
</div>
I don't really understand AngularJs well enough at this point to figure out what is going on. What do you think I should do to fix this?
Oh God I did it again. So it turns out that you gotta be careful about which version of bootstrap.css you are using. If its one that Angular-UI does not support, you'll get all that funny business going on.
Replacing the css with the following helped fix this problem.
https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css
Version 4 was too advanced for ui.bootstrap.
I have a simple directive with transcluded html.
I want to be able to inject directive scope params to the transclude.
I wrote a simple example in plunker :
https://plnkr.co/edit/jqyiQdgQxbeTrzyidZYF?p=preview
I know in angular 4 it can be done, but I can't find a good way to do it in angularjs.
// Code goes here
var app = angular.module("app", []);
app.controller("mainCtrl", function($scope) {
$scope.users = ["tal", "oren", "orel", "shluki"];
$scope.deleteUser = (user) => {alert("trying to delete", user);}
});
app.directive('myList', function myList() {
return {
restrict: 'E',
transclude: true,
template: "<div><table><tr ng-repeat='item in collection'><td> This is inside myList - user name: {{item}} <ng-transclude></ng-transclude></td></tr></table></div>",
scope: {
collection: "="
},
replace: true
};
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angularjs#1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="mainCtrl">
<h1>Hello Plunker!</h1>
<my-list collection="users">
<h2>This is transclude</h2>
<button ng-click="deleteUser(user)">Delete user: {{user ? user : "User name should be here"}}</button>
</my-list>
</body>
</html>
Will really appreicate some help.
plunker: https://plnkr.co/edit/jqyiQdgQxbeTrzyidZYF?p=preview
Here's a working plunker with your example.
http://plnkr.co/edit/BjSowyQdLXd0xoCZFqZ6?p=preview
The idea is to pass it as contents and not html as string. $compile is here because the link is done after ng-repeats already has transcluded its own template.
var template = '<h1>I am foo</h1>\
<div ng-repeat="item in users">\
<placeholder></placeholder>\
<hr>\
</div>';
var templateEl = angular.element(template);
transclude(scope, function(clonedContent) {
templateEl.find("placeholder").replaceWith(clonedContent);
$compile(templateEl)(scope, function(clonedTemplate) {
element.append(clonedTemplate);
});
});
If you want a proper explanation of what the problem was you should check the detailed answer here : Pass data to transcluded element
Hope this helped you out
Still learning angular, I would like to tap on an item from a list and show alert with the name of the item that was tapped.
In mainMenu.html ng-click is registered with the list element ng-click="mainMenuSelection(item.name), but the alert(name) is not being called in controllers.js
What am I doing wrong? Thanks
I also noticed the Google Chrome Sources does not show the views folder which contains mainMenu.html as per the second image.
//---app.js-----------------------------------------------
(function () {
'use strict';
angular
.module('angApp', ['ngRoute'])
.config(['$routeProvider', routeProvider]);
})();
function routeProvider ($routeProvider) {
$routeProvider.when('/list', {
templateUrl: 'views/mainMenu.html',
controller: 'MainMenuCtrl'
}).otherwise({ //home page
redirectTo: '/list'
});
}
angular.element(document).ready(function () {
angular.bootstrap(document, ['angApp']);
});
//---controllers.js-----------------------------------------------
angular
.module('angApp')
.controller('MainMenuCtrl', ['$scope', '$http', MainMenuCtrl]);
function MainMenuCtrl ($scope, $http) {
$http.get('js/mainMenu.json').then(
function (response) {
$scope.menuItems = response.data;
},
function (error) {
alert("http error");
}
)
$scope.mainMenuSelection = function(item) {
alert(item);
}
}
//---headerCtrl.js-----------------------------------------------
angular
.module('angApp')
.controller('HeaderCtrl', ['$scope', HeaderCtrl]);
function HeaderCtrl() {
var vm = this;
vm.title = "Tap left menu \u2630";
vm.headerTitle = setHeaderTitle;
function setHeaderTitle(title) {
vm.title = title;
}
}
//---index.html-----------------------------------------------
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="css/index.css">
<base href="http://localhost:63342/an1/">
<script src="angular.js"></script>
<script src="angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers/controllers.js"></script>
<script src="js/controllers/headerCtrl.js"></script>
<meta name="viewport" content="width=device-width" />
</head>
<body>
<main ng-view></main>
</body>
</html>
//---mainMenu.html-----------------------------------------------
<section class="mainMenu">
<ul>
<li ng-repeat="item in menuItems" ng-click="mainMenuSelection(item.name)">
<image src="images/{{item.image}}.png"></image>
{{item.name}}
</li>
</ul>
</section>
I created a fiddle with a working example close to what you want.
Obviously, I have a much pared down version for the sake of brevity.
http://jsfiddle.net/frishi/U3pVM/21624/
(function () {
'use strict';
angular
.module('angApp', [])
.controller("MainMenuCtrl", MainMenuCtrl)
})();
function MainMenuCtrl ($scope, $http) {
$scope.menuItems = [{
name:"Tom"},
{name: "Harry"},
{name: "Wiley"}
]
$scope.mainMenuSelection = function(item) {
alert(item);
}
}
Markup:
<div ng-app="angApp">
<section class="mainMenu" ng-controller="MainMenuCtrl">
<ul>
<li ng-repeat="item in menuItems" ng-click="mainMenuSelection(item.name)">
<image src="images/{{item.image}}.png" />
{{item.name}}
</li>
</ul>
</section>
</div>
I used a hard-coded JSON array of objects.
I also don't bootstrap the app the way you do.
There is too little information that your question provides, as to what could be the fault. Follow the example as specified in the fiddle, and if that doesn't work, reply with more details.
Here is my version in Plunker. I was trying to follow your file structure.
Make sure that <body ng-app="angApp"> is there, thats only one thing that I've added (I now it looks too trivial...)
EDIT: adding Git repo
Git repo with working code => clone => cd to directory => npm instal = npm start => files will be served on port:63342 (serving file using node sever in order to replicate environment where issue is happening)
This is my Index page
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<script src="~/Scripts/angular.min.js"></script>
<script src="~/Content/efDirective.js"></script>
<script src="~/Content/EmployeeForms.js"></script>
<html ng-app="AngularModule">
<body>
<div employee-form></div>
</body>
</html>
This is DirectiveJs
var app = angular.module("AngularModule", []);
app.directive("employeeForm", function () {
debugger;
return {
restrict: 'EA',
//template: 'helloworld',
templateUrl: 'Content/efTemplate.html'
}
});
Content in efTemplate.html is not displaying on index.cshtml page.
Check the message in browser console, probably there will be some error message. Maybe the url to template is not correctly resolved?
Did you specify the base url for angular?
The other option is to pre-render the template directly in your html index file. That has the benefit of saving the extra http request.
Like this:
<script type="text/ng-template" id="templateUrl">
<h1>your template </h1>
</script>
Example here https://docs.angularjs.org/api/ng/directive/script
I am trying to use this plugin http://prrashi.github.io/rateYo/ and for some reason when my artistpage.html page is served up the stars aren't appearing. I know the page is being served up because all other elements in the view appear. Something else that is strange is that when I put <div id="rateYo"></div> in the index.html the plugin works. So I am not really sure why its not working when the view is injected into <div ng-view></div>. Assuming my paths are correct, what could be the problem?
index.html
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js">
</script>
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-route.min.js"></script>
<link rel="stylesheet" type="text/css" href="/css/styles.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="./lib/jquery.rateyo.css"/>
</head>
<body ng-app='LiveAPP'>
<div ng-view></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="./lib/jquery.rateyo.js"></script>
<script src="/controllers/mainCtrl.js"></script>
<script src="/controllers/signUpCtrl.js"></script>
<script src="/controllers/artistCtrl.js"></script>
<script src="/routes.js"></script>
<script src="./js/stars.js"></script>
</body>
</html>
artistpage.html
<h1>This is a title</h1>
<div id="rateYo"></div>
routes.js
angular.module('LiveAPP', ['ngRoute',
'LiveAPP.main',
'LiveAPP.signUp',
'LiveAPP.artist'])
.config(function($routeProvider, $httpProvider) {
$routeProvider
.when('/', {
templateUrl : '/home.html',
controller : 'mainCtrl'
})
.when('/signup',{
templateUrl : '/signup.html',
controller : 'signUpCtrl'
})
.when('/artist',{
templateUrl : '/artistpage.html',
controller : 'signUpCtrl'
})
});
stars.js
$(function () {
$("#rateYo").rateYo({
rating: 3.6
});
});
The code in stars.js is evaluated when the document is ready, but jQuery has no knowledge of Angular replacing the view content in ng-view, so it won't attach the rating plugin to any newly added elements. Generally, you want to wrap jQuery plugins in Angular directives so that you can use them the "Angular way." For example:
app.directive("rateYo", function() {
return {
restrict: "A",
scope: {
rating: "="
},
template: "<div id='rateYo'></div>",
link: function( scope, ele, attrs ) {
$(ele).rateYo({
rating: scope.rating
});
}
};
});
Which would be used like this in your view:
<!-- assuming $scope.myRating equals the rating you want to display -->
<div rate-yo rating="myRating"></div>
Code above is untested, but it should give you the gist of it.