can not add text box input in table - angularjs

I have the following code :
http://plnkr.co/edit/RqLurBaCsgjQjOYMtl8r?p=preview
here there is a textbox and when user add something to the textbox and push add button then the entered text should be added to the table Here is my javaScript code:
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 service = {
addTable : addTable,
getData : getData,
};
return service;
function addTable(data) {
typesHash.push(data);
}
function getData() {
return typesHash;
}
});
app.controller('table', function(Service) {
//get the return data from getData funtion in factory
this.typesHash = Service.getData();
this.testData = {
id : '1',
name : "test",
price : 100,
unit : 2.5
};
//get the addtable function from factory
this.addTable = Service.addTable;
});
here as far as testData is static as follow it works:
this.testData = {
id : '1',
name : "test",
price : 100,
unit : 2.5
};
but here the text in the textbox is not added so I changed the above code as follow:
this.testData = {
id : '1',
name : $("#txt").val(),
price : 100,
unit : 2.5
};
the name gets nothing and row is added but name spot is empty?
Just a quick note that this is a simpler version of my real code and I have a reason to use factory.
Can ahyone help me to find out why this table does not connect to textbox correctly?

Modified version of the plnkr (ooo nice design changes SO).
Updated pasted a bad plnkr link before.
http://plnkr.co/edit/4g7LGRLBNEH2LeuEm1qN?p=preview
code from the post, let me know if this doesn't cover some scenario you were imagining. I tried getting rid of all the style cruft, that should be done in CSS or using things like text-right or text-center provided by bootstrap.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<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>
<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;
var service = {
addTable : addTable,
getData : getData,
};
return service;
function addTable(name) {
typesHash.push({id:localId++, name:name, price:100,unit:1});
}
function getData() {
return typesHash;
}
});
app.controller('table', function(Service) {
//get the return data from getData funtion in factory
this.typesHash = Service.getData();
//get the addtable function from factory
this.addTable = Service.addTable;
});
</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-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 ng-controller="table as iterateTb">
<tr ng-repeat="x in iterateTb.typesHash track by x.id">
<td>
<div>{{x.name}}</div>
</td>
<td>
<input type="text" ng-model="x.name"/>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

here is the updated plunker :-
http://plnkr.co/edit/uDIEAjRtpM7MnQu72LAA?p=preview
I just added data.name=$("#txt").val(); before pushing the data into array.
function addTable(data) {
data.name=$("#txt").val();
typesHash.push(data);
}
Hope it helps :-)

Related

Reactjs do not re-render when children node changed

I contrusted a table-form with two children node buttons and rows using Reactjs.
After change the value of each child node, the parent node receive the new state,
but no re-render happened, why?
<!DOCTYPE html>
<html>
<head>
<title> w3du </title><meta charset="utf-8">
<!-- Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
<style>
.quarcol {
width:25%
}
.vmidcol {
vertical-align:middle
}
.cyan {
color:#fff;
background-color:#63aae7
}
.blue {
color:#fff;
background-color:#60a0e0
}
</style>
</head>
<body>
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title text-center">Panel</h3>
</div>
<div id="canvas"></div>
</div>
</div>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.js"></script>
<script src="https://cdn.bootcss.com/react/15.6.1/react.js"></script>
<script src="https://cdn.bootcss.com/react/15.6.1/react-dom.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.js"></script>
<script src="https://cdn.bootcss.com/js-signals/1.0.0/js-signals.js"></script>
<script type="text/babel">
The 'table-row' stuff, the 3rd column is number, after modified, the associated button doesn't changed its value, vice versa
var BudgetTableRow = React.createClass({
getInitialState : function(){
return {
n : this.props.n,
price : this.props.price
};
},
handleChangeNum : function(e){
this.setState({
n : e.target.value
});
this.props.callback(this.props.idx, e.target.value);
},
render : function(){
var styfull = {
width : '100%',
height : '30%',
};
var stycenter = {
verticalAlign : 'middle',
horizontalAlign : 'middle'
};
return (
<tr className={this.props.color}>
<td className="quarcol text-center monofont" style={stycenter}>
<a href="#" data-toggle="tooltip" title={"<h1>"+this.props.label+"</h1>"}>{this.props.name}</a>
</td>
<td className="quarcol"><input name={this.props.label+'-price'}
className="form-control text-center monofont"
type="text" defaultValue={this.state.price} style={styfull}
onChange={this.handleChangePrice}
/></td>
<td className="quarcol"><input name={this.props.label+'-n'}
className="form-control text-center monofont"
type="text" defaultValue={this.state.n} style={styfull}
onChange={this.handleChangeNum} onFocus={this.handleFocus} onBlur={this.handleBlur}
/></td>
<td className="quarcol text-center monofont" style={stycenter}>
{this.state.price * this.state.n}
</td>
</tr>
);
}
});
The 'button' stuff, after modified, the associated table-row doesn't changed its value
var BudgetTableButton = React.createClass({
getInitialState : function(){
return {
n : this.props.n
};
},
handelClick : function(e){
e.preventDefault();
var n = (this.state.n=="0" || this.state.n=="") ? "1" : "0";
this.setState({
n : n
});
this.props.callback(this.props.idx, n);
},
render : function(){
var cls = (this.state.n=="0" || this.state.n=="") ? null : 'btn-info';
return (
<button className={'btn ' + cls} onClick={this.handelClick}>{this.props.label} {this.state.n}</button>
);
}
});
The parent node, the console.log() does right, but the form doesn't re-render, i used unique-key, is it something wrong with this.state.items.map ?
var BudgetTable = React.createClass({
getInitialState : function(){
return {
items : this.props.items
};
},
handleCallback : function(idx, n){
var items = this.state.items;
items[idx].n = n;
this.setState({
items : items
});
},
render : function(){
console.log(this.state.items[0]);
return (
<table className="table monofont">
<thead>
<tr className="blue">
<td className="text-center" colSpan="4">Table</td>
</tr>
</thead>
<tbody>
<tr><td colSpan="4">
{this.state.items.map((it, idx) =>
<BudgetTableButton key={it.label+'r'} label={it.label} idx={idx} callback={this.handleCallback} n={it.n} />
)}
</td></tr>
{this.state.items.map((it, idx) =>
<BudgetTableRow key={it.label+'b'} label={it.label} name={it.name} price={it.price} idx={idx} callback={this.handleCallback} n={it.n} />
)}
</tbody>
</table>
);
}
});
function init(){
return [
{
"price": 1340,
"name": "shoe",
"label": "Q41",
"n" : 1
}, {
"price": 1290,
"name": "clothes",
"label": "Q42",
"n" : 1
}
];
}
ReactDOM.render(
<BudgetTable items={init()} />,
document.getElementById("canvas")
);
</script>
</body>
</html>
The problem in your example is that you are using two states.
(I will talk here about the button component, but both cases are the same)
As you probably already know, the local state can only trigger update on the component it belongs to.
You are trying to sync the button's state with the state of the main app. However getInitialState is only called on initial render and not on re-render (info here).
In order to do what you want, you will need to get the button/row information from the props and not from the state (you already have them in props).
Furthermore, I would delete the children's state at all, because you don't need it. It is better that you keep the state in the top level component and only pass props and functions (like the callback fn) down to the children.
So in this case, if you change the button to the following code, it works flawlessly:
var BudgetTableButton = React.createClass({
handelClick : function(e){
e.preventDefault();
var n = this.props.n === "0" || this.props.n === "" ? "1" : "0";
this.props.callback(this.props.idx, n);
},
render : function(){
var cls = (this.props.n=="0" || this.props.n=="") ? null : 'btn-info';
return (
<button className={'btn ' + cls} onClick={this.handelClick}>{this.props.label} {this.props.n}</button>
);
}
});
You are not mutating the state.
handleCallback : function(idx, n){
var items = [...this.state.items];
items[idx].n = n;
this.setState({
items : items
});
}

Why does the Ajax not updating the model correctly?

I am new to angularjs and is using code sample in book "pro-angularjs" to do some test run (it has an initial list of items, but then use Ajax to update list):
<!DOCTYPE html>
<html ng-app="todoApp">
<head>
<title>TO DO List</title>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
<script src="angular.js"></script>
<script>
var model = {
user: "Adam",
items: [{ action: "Buy Flowers", done: false },
{ action: "Get Shoes", done: false },
{ action: "Collect Tickets", done: true },
{ action: "Call Joe", done: false }],
};
var todoApp = angular.module("todoApp", []);
todoApp.run(function ($http) {
$http.get("todo.json").then(function successCallback(data) {
model.items = data;
});
});
todoApp.filter("checkedItems", function () {
return function (items, showComplete) {
var resultArr = [];
angular.forEach(items, function (item) {
if (item.done == false || showComplete == true) {
resultArr.push(item);
}
});
return resultArr;
}
});
todoApp.controller("ToDoCtrl", function ($scope) {
$scope.todo = model;
$scope.incompleteCount = function () {
var count = 0;
angular.forEach($scope.todo.items, function (item) {
if (!item.done) { count++ }
});
return count;
}
$scope.warningLevel = function () {
return $scope.incompleteCount() < 3 ? "label-success" : "label-warning";
}
$scope.addNewItem = function (actionText) {
$scope.todo.items.push({ action: actionText, done: false });
}
});
</script>
</head>
<body ng-controller="ToDoCtrl">
<div class="page-header">
<h1>
{{todo.user}}'s To Do List
<span class="label label-default" ng-class="warningLevel()"
ng-hide="incompleteCount() == 0">
{{incompleteCount()}}
</span>
</h1>
</div>
<div class="panel">
<div class="input-group">
<input class="form-control" ng-model="actionText" />
<span class="input-group-btn">
<button class="btn btn-default"
ng-click="addNewItem(actionText)">Add</button>
</span>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Description</th>
<th>Done</th>
</tr>
</thead>
<tbody>
<tr ng-repeat=
"item in todo.items | checkedItems:showComplete | orderBy:'action'">
<td>{{item.action}}</td>
<td><input type="checkbox" ng-model="item.done" /></td>
</tr>
</tbody>
</table>
<div class="checkbox-inline">
<label><input type="checkbox" ng_model="showComplete"> Show Complete</label>
</div>
</div>
</body>
</html>
the only change i made was:
todoApp.run(function ($http) {
$http.get("todo.json").then(function successCallback(data) {
model.items = data;
});
});
it was initially:
$http.get("todo.json").success(function (data) {
model.items = data;
});
which does not run with the latetest version angularjs, and so i made the change.
when debugging, i found that the initial value of model.items is:
and it is correctly showing in UI (see left side of screenshot).
After the ajax, its value is updated to 'data' whose value is:
the value of data looks fine to me (same as initial value of items).
But after i let go the debugger, finally in UI all items are gone.
I do understand why? it seems 'items' is the same as 'data'. Anyone has a clue on how i can debug further to find out the root cause?
Thanks,
btw, the 'todo.json' i used is below:
[{ "action": "Buy Flowers", "done": false },
{ "action": "Get Shoes", "done": false },
{ "action": "Collect Tickets", "done": true },
{ "action": "Call Joe", "done": false }]
You are not updating your model correctly. As you can see from your screenshot, data contains an object data which should be assigned to your model.
todoApp.run(function ($http) {
$http.get("todo.json").then(function successCallback(data) {
model.items = data.data;
});
});

Angular two way data-binding dosn´t update table in different route

I have an angular app, and an index.html with an ng-view that renders to different views partials/persons.html and partials/newPerson.html.
when i add a new person to the $scope.persons in my controller via the newPerson.html the $scope.persons is updated, but it dosn´t updated the table in the partials/persons.html. if i copy/paste the table into partials/newPerson.html the table is updated automatically. I cant seem to wrap my head around why? they are using the same controller...?
thank´s in advance for your help :)
js/app.js
var app = angular.module('app',['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/persons',{
templateUrl:'partials/persons.html',
controller:'PersonCtrl'
})
.when('/newperson',{
templateUrl:'partials/newPerson.html',
controller:'PersonCtrl'
})
.otherwise({
redirectTo: '/'
});
});
app.controller('PersonCtrl',['$scope', function($scope){
var persons = [
{
id: 1
,name: "Jens",
age : 18}
,{
id: 2,
name: "Peter",
age : 23
}
,{
id: 3
,name: "Hanne"
,age : 23
}
];
$scope.persons = persons;
$scope.nextId = 4;
$scope.savePerson = function(){
if($scope.newPerson.id === undefined)
{
$scope.newPerson.id= $scope.nextId++;
$scope.persons.push($scope.newPerson);
}else{
for (var i = 0; i < $scope.persons.length; i++) {
if($scope.persons[i].id === $scope.newPerson.id){
$scope.persons[i] = $scope.newPerson;
break;
}
}
}
$scope.newPerson = {};
};
index.html
<html ng-app="app" ng-controller="PersonCtrl">
<head>
<title>Routing</title>
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular-route.js"></script>
<script src="https://code.angularjs.org/1.4.7/i18n/angular-locale_da.js"></script>
<script src="angularSrc/app.js"></script>
</head>
<body>
<br>
<div class="container">
<header>
<h1>People Routing</h1>
<nav>
persons
new person
</nav>
</header>
<div ng-view="ng-view">
</div>
</div>
</body>
partials/persons.html
<h3>Persons</h3>
<table >
<thead>
<tr>
<td>Id</td>
<td>name</td>
<td>age</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="p in persons">
<td>{{p.id}} </td>
<td>{{p.name}} </td>
<td>{{p.age}} </td>
</tr>
</tbody>
</table>
partials/newPerson.html
<div >
<h1>New person</h1>
<form class="form-horizontal">
<fieldset>
<div class="form-group">
<input type="text" ng-model="newPerson.name" model="newPerson.name" class="form-control" id="year" placeholder="name">
</div>
<div class="form-group">
<input type="number" ng-model="newPerson.age" model="newPerson.age" class="form-control" id="age" placeholder="age">
</div>
</fieldset>
</form>
<button type="submit" ng-click="savePerson()" >Save</button>
<h2>nextId: {{nextId}}</h2>
</div>
The problem is that you aren't realizing that each use of controller creates new instance.
The scope is destroyed when you leave a controller so if you add to the scope in one instance , that change will be lost when you load controller again on your other route.
You need to use a service to persist the data during the life of each page load.
Simple service example:
app.factory('PersonService', function () {
var persons = [{
id: 1,
name: "Jens",
age: 18
}, {
...
}, {
...
}];
return {
persons: persons
}
});
Then inject in controller and use the service data in controller
app.controller('PersonCtrl',['$scope','PersonService', function($scope,PersonService){
$scope.persons = PersonService.persons;

when I put ng-controller in div instead of body autocomplete stops working

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

Custom directive breaking code in AngularJS

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

Resources