I deployed a simple AngularJS app(which is working perfectly fine on local) into Heroku, then looks like "ng-repeat" stops working for some reason, there is no error from heroku logs. hopefully someone could give some hints.
project source:
run it on local:
npm installn.
node index.js
run it on heroku:
git clone
heroku create
git add .
git commit -m "initial commit"
git push heroku master
heroku ps:scale web=1
heroku open
index.js
var express = require('express');
var app = express();
var path = require('path');
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/scripts'));
app.use(express.static(__dirname + '/scripts/lib'));
app.use(express.static(__dirname + '/scripts/services'));
app.use(express.static(__dirname + '/scripts/controllers'));
app.get('/',function(req,res){
res.sendFile(path.join(__dirname+'/index.html'));
//__dirname : It will resolve to your project folder.
});
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
index.html
<html ng-app="albumsApp">
<head>
<meta charset="utf-8">
<title>Albums Store</title>
<!-- CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/3.3.0/ekko-lightbox.min.css">
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
<!-- JS Libs -->
<script src="jquery.min.js"></script>
<script src="bootstrap.min.js"></script>
<script src="ekko-lightbox.min.js"></script>
<script src="angular.min.js"></script>
<script src="angular-animate.min.js"></script>
<script src="lodash.min.js"></script>
<!-- modules / services / controllers -->
<script src="app.module.js"></script>
<script src="album_service.js"></script>
<script src="album.js"></script>
<script src="user.js"></script>
<!-- lightbox delegation -->
<script type="text/javascript">
$(document).ready(function ($) {
// delegate calls to data-toggle="lightbox"
$(document).delegate('*[data-toggle="lightbox"]:not([data-gallery="navigateTo"])', 'click', function(event) {
event.preventDefault();
return $(this).ekkoLightbox({
onShown: function() {
if (window.console) {
return console.log('Checking our the events huh?');
}
},
onNavigate: function(direction, itemIndex) {
if (window.console) {
return console.log('Navigating '+direction+'. Current item: '+itemIndex);
}
}
});
});
//Programatically call
$('#open-image').click(function (e) {
e.preventDefault();
$(this).ekkoLightbox();
});
});
</script>
</head>
<body>
<h1>Albums Library</h1>
Search: <input ng-model="query" type="text"/>
<div ng-controller="albumCtrl">
<table class="pure-table pure-table-bordered">
<thead>
<tr>
<th><a href="" ng-click="sortField = 'id'; reverse = !reverse" >Album ID</a></th>
<th>Album Title</th>
<th><a href="" ng-click="sortField = 'userId'; reverse = !reverse" >User Name</a></th>
</tr>
</thead>
<tr ng-repeat="album in albums | orderBy:sortField:!reverse | filter:query">
<td>{{album.id}}</td>
<td>
<div id="title_container" class="pure-g">
<div class="pure-u-3-5">{{album.title}}</div>
<div class="pure-u-1-5"><input type="checkbox" ng-model="shouldShow" /></div>
<div class="pure-u-1-5" ng-show="shouldShow">
<a href="{{album.url}}" data-toggle="lightbox">
<img ng-src="{{album.thumbnailUrl}}" class="img-responsive">
</a>
</div>
</div>
</td>
<td>{{album.userId}}</td>
</tr>
</table>
</div>
<!-- testing data
<div ng-controller="userCtrl" class="pure-u-1-2">
<table class="pure-table pure-table-bordered">
<thead>
<tr>
<th><a href="" ng-click="sortField = 'id'; reverse = !reverse" >User ID</a></th>
<th><a href="" ng-click="sortField = 'name'; reverse = !reverse" >User Name</a></th>
<th>Email</th>
</tr>
</thead>
<tr ng-repeat="user in users | orderBy:sortField:!reverse | filter:query">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.email}}</td>
</tr>
</table>
</div>
-->
</body>
</html>
package.json
{
"name": "angularjs-study",
"version": "1.0.0",
"description": "project for AngularJS self-studying with fake data from JSONplaceholder & faker.js",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "4.13.3",
"gzippo": "^0.2.0",
"path": "^0.12.7"
},
"engines": {
"node": "0.12.7"
},
"repository": {
"type": "git",
"url": "git+https://github.com/igxz/angularjs-study.git"
},
"keywords": [
"angularjs",
"node",
"heroku",
"express"
],
"author": "Stephen Zhang",
"license": "MIT",
"bugs": {
"url": "https://github.com/igxz/angularjs-study/issues"
},
"homepage": "https://github.com/igxz/angularjs-study#readme"
}
scripts/services/album_service.js
angular
.module('albumsApp')
.factory('albumService', albumService);
function albumService($http){
return {
fetch_all_albums: function(){
return $http.get('http://jsonplaceholder.typicode.com/albums');
},
fetch_all_users: function(){
return $http.get('http://jsonplaceholder.typicode.com/users');
},
fetch_all_photos: function(){
return $http.get('http://jsonplaceholder.typicode.com/photos');
},
id_to_name: function(albums, users){
angular.forEach(albums, function(album){
var userName = _.select(users, function(u){
return u.id === album.userId;
})[0].name;
album.userId = userName;
});
},
add_photo_urls: function(albums, photos){
angular.forEach(albums, function(album){
var matchedPhoto = _.select(photos, function(p){
return p.albumId === album.id;
})[0];
var thumbnailUrl = matchedPhoto.thumbnailUrl;
var url = matchedPhoto.url;
// add key/value
album['thumbnailUrl'] = thumbnailUrl;
album['url'] = url;
});
}
};
}
Procfile
web: node index.js
I got screen shots of how output looks like both from local & heroku, bud I don't have enough reputation to post here : (
Solved
it's working on Netify with no code update, I guess it could be heroku env issue then, Netify makes process much easier
it can be accessed from http://json-placeholder-example.netlify.com/
If the ng-repeat was working before and stopped and no error is being thrown the most likely reason is that there's no data being retrieved. Test your data retrieval outside of the page to see if that's the case.
Related
**How to add pagination using angular js in jquery Datatable plugin. There is some external plugin available like angular js data table that directly allows pagination but i want to make inside jquery data table. **
var app= angular.module("myModule",['ui-bootstrap']);
app.controller("dataController",function($scope,$http){
$http({
method: 'GET',
url: 'https://api.myjson.com/bins/833qv'
}).then(function successCallback(response) {
$scope.employees=response.data;
console.log($scope.employees);
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<title>Angula js | Home </title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div ng-app="myModule">
<input type="text" ng-model="searchFilter" />
<div ng-controller="dataController">
<table style="width:500px;border:2px solid black;">
<thead>
<tr style="text-align:left;">
<th>Id</th>
<th>Client name</th>
<th>Client code</th>
<th>Team id</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="employee in employees">
<td>{{employee.id}}</td>
<td>{{employee.client_name}}</td>
<td>{{employee.client_code}}</td>
<td>{{employee.team_id}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="custom.js"></script>
</body>
</html>
its not accepting datatable pagination. can it possible that angular js accept datatable jqyery pagination.
Pagination:
HTML part
<ul>
<li class="paginationclass" style="font-weight:bold;"><span>Name</span><span>Age</span><span>Designation</span></li>
<li class="paginationclass" ng-repeat="datalist in datalists | pagination: curPage * pageSize | limitTo: pageSize">
<div><span>{{ datalist.name }} </span><span>{{ datalist.age }}</span><span>{{ datalist.designation }}</span></div>
</li>
</ul>
<div class="pagination pagination-centered" ng-show="datalists.length">
<ul class="pagination-controle pagination">
<li>
<button type="button" class="btn btn-primary" ng-disabled="curPage == 0"
ng-click="curPage=curPage-1"> < PREV</button>
</li>
<li>
<span>Page {{curPage + 1}} of {{ numberOfPages() }}</span>
</li>
<li>
<button type="button" class="btn btn-primary"
ng-disabled="curPage >= datalists.length/pageSize - 1"
ng-click="curPage = curPage+1">NEXT ></button>
</li>
</ul>
</div>
</div>
</div>
JS part
var myapp = angular.module('sampleapp', [ ]);
myapp.controller('samplecontoller', function ($scope) {
$scope.showData = function( ){
$scope.curPage = 0;
$scope.pageSize = 3;
$scope.datalists = [
{ "name": "John","age":"16","designation":"Software Engineer1"},
{"name": "John2","age":"21","designation":"Software Engineer2"},
{"name": "John3","age":"19","designation":"Software Engineer3"},
{"name": "John4","age":"17","designation":"Software Engineer4"},
{"name": "John5","age":"21","designation":"Software Engineer5"},
{"name": "John6","age":"31","designation":"Software Engineer6"},
{"name": "John7","age":"41","designation":"Software Engineer7"},
{"name": "John8","age":"16","designation":"Software Engineer8"},
{"name": "John18","age":"16","designation":"Software Engineer9"},
{"name": "John28","age":"16","designation":"Software Engineer10"},
{"name": "John38","age":"16","designation":"Software Engineer11"},
{"name": "John48","age":"16","designation":"Software Engineer12"},
{"name": "John58","age":"16","designation":"Software Engineer13"},
{"name": "John68","age":"16","designation":"Software Engineer14"},
{"name": "John68","age":"16","designation":"Software Engineer15"}
]
$scope.numberOfPages = function() {
return Math.ceil($scope.datalists.length / $scope.pageSize);
};
}
});
angular.module('sampleapp').filter('pagination', function()
{
return function(input, start)
{
start = +start;
return input.slice(start);
};
});
Use this open source library basically enhanced version of JQuery DataTables to rendered tables which include pagination, sorting, searching and filtering and very good support of accessibility.
https://assets.cms.gov/resources/framework/2.0/Pages/datatables.html.
I am very new to Angular. Earlier I was using Javascript, but now I am learning AngularJs. Version currently using is 1.3.2.
Problem is I am trying to use local storage.
In Javascript, we use something similar to this:
localStorage.pic = data.pic;
localStorage.id = data.uid;
localStorage.name = data.name;
Is there anything similar to this in AngularJs?
Thanks for your advise.
It's the same way using ngStorage,
Add ngStorage reference and inject it as a depdency to your angular app,
<script type="text/javascript" src='https://rawgithub.com/gsklee/ngStorage/master/ngStorage.js'></script>
angular.module('gameApp', ['ngStorage'])
Then you can store and retrieve like this,
$localStorage.pic= $scope.pic;
DEMO
angular.module('gameApp', ['ngStorage', 'ui.bootstrap'])
.controller('MainCtrl', ['$scope', '$localStorage', function ($scope, $localStorage) {
// Set a total score variable equal to zero
$scope.total = 0;
// NOTE: use d3.js for data visualization in widget
var gameData = [
{
"level": "Level One",
"points": 30,
"max": 100,
"completed": false
},
{
"level": "Level Two",
"points": 50,
"max": 100,
"completed": false
}
];
// tie the game JSON to the view
$scope.gameData = gameData;
// tie the view to ngModule which saves the JSON to localStorage
$localStorage.gameData = gameData;
// loop through the gameData and sum all the values where the key = 'points'
console.log("Your current score is: " + $scope.total)
$localStorage.total = $scope.total;
$scope.addToLevel = function(level, num){
$scope.levelPoints = gameData[level].points += num;
console.log("You have " + $scope.levelPoints + " points in Level");
}
// create a function that loops the json to check if the points >= max
// and if so
// then change completed to true
$scope.calcTotal = function(){
for (var i in $scope.gameData){
var level = $scope.gameData[i];
$scope.total += level.points;
}
$localStorage.total = $scope.total;
};
$scope.calcTotal();
}])
<!DOCTYPE html>
<html ng-app='gameApp'>
<head>
<meta charset="utf-8" />
<title>Angular Local storage</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
<script type="text/javascript" src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js'></script>
<script type="text/javascript" src='https://rawgithub.com/gsklee/ngStorage/master/ngStorage.js'></script>
<script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.1.js"></script>
<script type="text/javascript" src='script.js'></script>
</head>
<body ng-controller='MainCtrl'>
<!-- Fixed navbar -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Angular JS Local Storage</a>
</div>
</div>
</nav>
<div class='container'>
<div class='row' style='margin-top:100px'>
<button class='btn btn-primary' ng-click="addToLevel(0, 20); calcTotal();">+20 Points Lvl 1</button>
<br>
<table class='table table-hover'>
<thead>
<tr>
<td>Level</td>
<td>Points</td>
</tr>
</thead>
<tbody>
<tr ng-repeat='data in gameData'>
<td>{{ data.level }}</td>
<td>{{ data.points }}</td>
</tr>
<tr>
<td>Total Points</td>
<td>{{total}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
You can create a common factory service that will save and return the saved local storage data based on the key.
app.factory('storageService', ['$rootScope', function($rootScope) {
return {
get: function(key) {
return localStorage.getItem(key);
},
set: function(key, data) {
localStorage.setItem(key, data);
}
};
}]);
In controller :
Inject the storageService dependency in the controller to set and get the data from the local storage.
app.controller('myCtrl',['storageService',function(storageService) {
// Set local storage data to storageService
storageService.set('key', 'value');
// Get saved local storage data from storageService
var data = storageService.get('key');
});
JavaScript will remain same whether you use angular or other frameworks.You are doing wrong , localStorage has setItem() and getItem() methods .
Try this
localStorage.setItem('pic',data.pic);
localStorage.setItem('id',data.id);
localStorage.setItem('name',data.name);
And retrieval like this
localStorage.getItem('pic');
localStorage.getItem('id');
localStorage.getItem('name');
I'm sure everyone has seen questions of a similar ilk, and trust me when I say I have read all of them in trying to find an answer. But alas without success. So here goes.
With the below code, why can I not get an alert?
I have an ASP.Net MVC4 Web API application with AngularJS thrown in. I have pared down the code as much as I can.
I know that my AngularJS setup is working correctly because on loading my view it correctly gets (via a Web API call) and displays data from the database into a table (the GetAllRisks function). Given that the Edit button is within the controller, I shouldn't have any scope issues.
NB: the dir-paginate directive and controls are taken from Michael Bromley's excellent post here.
I would appreciate any thoughts as my day has degenerated into banging my head against my desk.
Thanks,
Ash
module.js
var app = angular.module("OpenBoxExtraModule", ["angularUtils.directives.dirPagination"]);
service.js
app.service('OpenBoxExtraService', function ($http) {
//Get All Risks
this.getAllRisks = function () {
return $http.get("/api/RiskApi");
}});
controller.js
app.controller("RiskController", function ($scope, OpenBoxExtraService) {
//On load
GetAllRisks();
function GetAllRisks() {
var promiseGet = OpenBoxExtraService.getAllRisks();
promiseGet.then(function (pl) { $scope.Risks = pl.data },
function (errorPl) {
$log.error("Some error in getting risks.", errorPl);
});
}
$scope.ash = function () {
alert("Bananarama!");}
});
Index.cshtml
#{
Layout = null;
}
<!DOCTYPE html>
<html ng-app="OpenBoxExtraModule">
<head>
<title>Risks</title>
<link href="~/Content/bootstrap.min.css" rel="stylesheet">
<script type="text/javascript" src="~/Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="~/Scripts/bootstrap.min.js"></script>
<script type="text/javascript" src="~/Scripts/angular.js"></script>
<script type="text/javascript" src="~/Scripts/AngularJS/Pagination/dirPagination.js"></script>
<script type="text/javascript" src="~/Scripts/AngularJS/module.js"></script>
<script type="text/javascript" src="~/Scripts/AngularJS/service.js"></script>
<script type="text/javascript" src="~/Scripts/AngularJS/controller.js"></script>
</head>
<body>
<div ng-controller="RiskController">
<table>
<thead>
<tr>
<th>Risk ID</th>
<th>i3_n_omr</th>
<th>i3_n_2_uwdata_key</th>
<th>Risk Reference</th>
<th>Pure Facultative</th>
<th>Timestamp</th>
<th></th>
</tr>
</thead>
<tbody>
<tr dir-paginate="risk in Risks | itemsPerPage: 15">
<td><span>{{risk.RiskID}}</span></td>
<td><span>{{risk.i3_n_omr}}</span></td>
<td><span>{{risk.i3_n_2_uwdata_key}}</span></td>
<td><span>{{risk.RiskReference}}</span></td>
<td><span>{{risk.PureFacultative}}</span></td>
<td><span>{{risk.TimestampColumn}}</span></td>
<td><input type="button" id="Edit" value="Edit" ng-click="ash()"/></td>
</tr>
</tbody>
</table>
<div>
<div>
<dir-pagination-controls boundary-links="true" template-url="~/Scripts/AngularJS/Pagination/dirPagination.tpl.html"></dir-pagination-controls>
</div>
</div>
</div>
</body>
</html>
you cannot use ng-click attribute on input with angularjs : https://docs.angularjs.org/api/ng/directive/input.
use onFocus javascript event
<input type="text" onfocus="myFunction()">
or try to surround your input with div or span and add ng-click on it.
I've got the working demo of your app, code (one-pager) is enclosed below, but here is the outline:
removed everything concerning dirPagination directive, replaced by ngRepeat
removed $log and replaced by console.log
since I don't have a Web API endpoint, I just populated $scope.Risks with some items on a rejected promise
Try adjusting your solution to first two items (of course, you won't populate it with demo data on rejected promise)
<!doctype html>
<html lang="en" ng-app="OpenBoxExtraModule">
<head>
<meta charset="utf-8">
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
var app = angular.module("OpenBoxExtraModule", []);
app.service('OpenBoxExtraService', function ($http) {
//Get All Risks
this.getAllRisks = function () {
return $http.get("/api/RiskApi");
}
});
app.controller("RiskController", function ($scope, OpenBoxExtraService) {
//On load
GetAllRisks();
function GetAllRisks() {
var promiseGet = OpenBoxExtraService.getAllRisks();
promiseGet.then(function (pl) { $scope.Risks = pl.data },
function (errorPl) {
console.log("Some error in getting risks.", errorPl);
$scope.Risks = [{RiskID: "1", i3_n_omr: "a", i3_n_2_uwdata_key: "b", RiskReference: "c", PureFacultative:"d", TimestampColumn: "e"}, {RiskID: "2", i3_n_omr: "a", i3_n_2_uwdata_key: "b", RiskReference: "c", PureFacultative:"d", TimestampColumn: "e"}, {RiskID: "3", i3_n_omr: "a", i3_n_2_uwdata_key: "b", RiskReference: "c", PureFacultative:"d", TimestampColumn: "e"} ];
});
}
$scope.ash = function () {
alert("Bananarama!");}
});
</script>
</head>
<body>
<div ng-controller="RiskController">
<table>
<thead>
<tr>
<th>Risk ID</th>
<th>i3_n_omr</th>
<th>i3_n_2_uwdata_key</th>
<th>Risk Reference</th>
<th>Pure Facultative</th>
<th>Timestamp</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="risk in Risks">
<td><span>{{risk.RiskID}}</span></td>
<td><span>{{risk.i3_n_omr}}</span></td>
<td><span>{{risk.i3_n_2_uwdata_key}}</span></td>
<td><span>{{risk.RiskReference}}</span></td>
<td><span>{{risk.PureFacultative}}</span></td>
<td><span>{{risk.TimestampColumn}}</span></td>
<td><input type="button" id="Edit" value="Edit" ng-click="ash()"/></td>
</tr>
</tbody>
</table>
<div>
<div></div>
</div>
</div>
</body>
</html>
Thank you all for your help, particularly #FrailWords and #Dalibar. Unbelievably, this was an issue of caching old versions of the javascript files. Doh!
You can't directly use then on your service without resolving a promise inside it.
fiddle with fallback data
this.getAllRisks = function () {
var d = $q.defer();
$http.get('/api/RiskApi').then(function (data) {
d.resolve(data);
}, function (err) {
d.reject('no_data');
});
return d.promise;
}
This will also fix your problem with getting alert to work.
I have a textbox with autocomplete capability and after clicking on click me button the text in autocomplete is added as in the table , here is the link that works perfectly fine,
var app = angular.module('app', []);
app.factory('Service', function() {
var typesHash = [ {
id :1,
name : 'lemon',
price : 100,
unit : 2.5
}, {
id : 2,
name : 'meat',
price : 200,
unit : 3.3
} ];
var localId = 3;
availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
var service = {
addTable : addTable,
getData : getData,
complete:complete
};
return service;
function complete($scope){
$( "#txt" ).autocomplete({
source: availableTags,
messages: {
noResults: '',
results: function() {}
}
});
$("#txt" ).on( "autocompleteselect", function( event, ui ) {
$scope.tableTools.inputData=ui.item.value;
} );
}
function addTable(name,price) {
typesHash.push({id:localId++, name:name, price:price,unit:1});
}
function getData() {
return typesHash;
}
});
app.controller('table', function(Service,$scope) {
//get the return data from getData funtion in factory
this.typesHash = Service.getData();
//get the addtable function from factory
this.addTable = Service.addTable;
this.complete=Service.complete($scope);
});
working link
but as soon as I put ng-controller="table as tableTools" in the div instead of body then autocompleting of text box start acting funny and it does not work properly
not working link
can anyone explain the reason and tell me how I can fix it in a way that even by putting ng-controller="table as tableTools" inside div it works?
Update:
here is the error:
Uncaught TypeError: Cannot set property 'inputData' of undefined
for this line:
$scope.tableTools.inputData = ui.item.value;
(remember the problem starts after you click on suggested text)
The issue is hidden in missunderstanding of the angularjs object life-cycles.
The most important here to know is:
services (factory/provider ... different creation, but at the end the same) are singletons
controllers are instantiated per each view. (There are many, multi instances of one controller through the angular app life time..)
So what happened?
There is one service:
app.factory('Service', function() {
...
and there is one controller passing its scope into that service
app.controller('table', function(Service,$scope) {
...
this.complete=Service.complete($scope);
And on the page we can see:
// first usage of controller
// its first instance is created, $scope is passed
<div class="row commonRow" ng-controller="table as tableTools">
// second usage
// different instance is created... and it also passes the §scope
<tbody ng-controller="table as iterateTb">
But as described above - service is only one. While first controller passes its $scope, the second does after while as well.. and that is causing the issue.
We can use services inside of controllers. That is the design principle of angular. But we should not pass the $scope...
This is happening because you have two controller on the same page with two differenct element therefore scope is not binding properly.
The best code for you to do this is :-
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<link data-require="bootstrap#*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<title>Insert title here</title>
<script>
var app = angular.module('app', []);
app.factory('Service', function() {
var typesHash = [ {
id :1,
name : 'lemon',
price : 100,
unit : 2.5
}, {
id : 2,
name : 'meat',
price : 200,
unit : 3.3
} ];
var localId = 3;
availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
var service = {
addTable : addTable,
getData : getData,
complete:complete
};
return service;
function complete($scope){
$( "#txt" ).autocomplete({
source: availableTags,
messages: {
noResults: '',
results: function() {}
}
});
$("#txt" ).on( "autocompleteselect", function( event, ui ) {
console.log($scope);
$scope.tableTools.inputData=ui.item.value;
} );
}
function addTable(name,price) {
typesHash.push({id:localId++, name:name, price:price,unit:1});
}
function getData() {
return typesHash;
}
});
app.controller('table', function(Service,$scope) {
//get the return data from getData funtion in factory
this.typesHash = Service.getData();
//get the addtable function from factory
this.addTable = Service.addTable;
this.complete=Service.complete($scope);
});
</script>
</head>
<body ng-app="app" ng-controller="table as tableTools" >
<form >
<div class="row commonRow" >
<div class="col-xs-1 text-right">
item:
</div>
<div class="col-xs-5">
<input id="txt" type="text" style="width: 100%;" ng-keyup="tableTools.complete()" ng-model="tableTools.inputData">
</div>
<div class="col-xs-2">
<button class="btn btn-primary" ng-click="tableTools.addTable(tableTools.inputData);tableTools.inputData=''">
click me
</button>
</div>
</div>
</form>
<div class="row commonRow">
<div class="col-xs-1"></div>
<div class="col-xs-10">
<table class="table table-hover">
<thead>
<tr>
<th>item</th>
</tr>
</thead>
<tbody> <!--No need for controller here-->
<tr ng-repeat="x in tableTools.typesHash track by x.id">
<td>
<div>{{x.name}}</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
Plunker
If you add
$scope.tableTools={}
right below
function complete($scope){
the second one works as expected.
can anyone explain the reason
As long as the object ‘$scope.tableTools‘ has not been defined, you cannot successfully add attributes to it
I need to add a custom directive to my code, but every time I add it, it breaks my code. I checked the console and is giving me the following error
Error: Argument 'guessGameController' is not a function, got undefined
at Error (native)
Now I am not sure if I am not setting my code right or if I am not adding the directive where is supposed to go. Here is my code, I appreciate all the help.
index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="guessGameApp">
<head>
<title>Word Game 2.0 - AngularJS</title>
<!--Encoding-->
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<!-- JQuery -->
<script src="js/jquery-1.11.0.min.js"></script>
<!--Scripts-->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js" type="text/javascript"></script>
<script src="js/controllers/app.js" type="text/javascript"></script>
<script src="js/controllers/maincontroller.js" type="text/javascript"></script>
<!--Styles-->
<link rel="stylesheet" type="text/css" href="css/magicWord.css">
<!--<script src="js/jquery-1.11.0.min.js"></script>-->
</head>
<body>
<div ng-controller="guessGameController">
<p>
<header id="masthead">
<h2 align="center">{{appTitle}}</h2>
</header>
</p>
<div ng-controller="wordController">
<p>
<table align="center" width="300px" height="150px" border="solid 2px">
<tr>
<td id="guessBox">
<p align="center">
<input value="" type="text" id="guestGuess" placeholder="Enter Guess" ng-model="guestGuess"/>
</p>
<p align="center"><button ng-click="addGuess()" id="guessButton">Click to Check</button></p>
</td>
</tr>
<tr>
<td>
<h3 align="center">Your guesses so far are: </h3>
<p align="center" ng-repeat="words in guesses">{{words}}</p>
</td>
</tr>
<tr>
<td>
<p align="center">You have guessed:<b>{{guessed}}</b> times out {{allowed}} chances.</p>
<p align="center">You have <b>{{allowed - guessed}}</b> guesses left.</p>
</td>
</tr>
<tr>
<td>
<a custom-button>Click me</a>
<br />
<button custom-button>Hello</button>
</td>
</tr>
</table>
</p>
</div>
</div>
</body>
</html>
app.js
var gameApp = angular.module('guessGameApp', []);
var gameTemplate = angular.module('guessGameApp', []);
maincontroller.js
gameApp.controller("guessGameController", function($scope)
{
$scope.appTitle = "WELCOME TO THE GUESS GAME!";
});
gameApp.controller('wordController', function($scope)
{
$scope.guess = '';
$scope.guesses = [];
$scope.guessed= '';
$scope.allowed = 6;
$scope.wordToGuess = "Just";
$scope.pushGuess = function () {
$scope.guesses.push($scope.guestGuess);
$scope.guessed = $scope.guesses.length;
$scope.resetGuess();
}
$scope.resetGuess = function() {
$scope.guestGuess = '';
}
$scope.addGuess = function()
{
if ($scope.guestGuess == null || $scope.guestGuess == '')
{
$("input[type=text]").ready(function () { $("#guestGuess").addClass("blur"); });
$scope.result = " Please enter a guess\n\nDon't leave the box empty.";
alert($scope.result);
}
else if ($scope.guestGuess.toLowerCase() == $scope.wordToGuess.toLowerCase())
{
$("input[type=text]").ready(function () { $("#guestGuess").removeClass("blur"); });
$scope.pushGuess(guestGuess);
$scope.result = "You have guessed the correct word. Way to go!\n\n\t\t The word was: ";
alert($scope.result + $scope.wordToGuess);
}
else if ($scope.guestGuess != $scope.wordToGuess & ($scope.allowed - $scope.guessed) > 1)
{
$("input[type=text]").ready(function () { $("#guestGuess").removeClass("blur"); });
$scope.pushGuess(guestGuess);
$scope.result = "Please try again!";
alert($scope.result);
}
else if (($scope.allowed - $scope.guessed) <= 1)
{
$("input[type=text]").ready(function () { $("#guestGuess").addClass("doneBlur"); });
$scope.guesses.push($scope.guestGuess);
$scope.guessed = $scope.guesses.length;
$scope.result = "Game over! The word was: ";
alert($scope.result + $scope.wordToGuess);
}
$scope.guess = '';
}
});
gameApp.directive('customButton', function ()
{
$scope.wordToGuess = "Just";
return {
restrict: 'A',
replace: true,
transclude: true,
templateUrl: '../../templates/customTemplate.HTML',
link: function (scope, element, attrs)
{
element.bind("click",function()
{
alert("The value of 'guessWord' is " + scope.wordToGuess);
})
}};
});
customTemplate.html
<a href="" class="myawesomebutton" ng-transclude>
<i class="icon-ok-sign"></i>
</a>
In app.js remove the second module declaration
var gameApp = angular.module('guessGameApp', []);
//var gameTemplate = angular.module('guessGameApp', []); --> remove this line
You are also modifying DOM from the controller, this is not the angular way. If you want to add classes when some condition occurs, then have a look at ng-class