im learning angularjs thru an Apress book and I've come across some code that doesnt work, ive tried to debug but my console isnt giving me any errors or anything. Maybe some experts can guide me thru whats wrong, thanks.
customFilters.js file
// Creating a custom filter
// arguments for the filter method is unique and a factory function that returns a filter function that does the actaul work
angular.module('customFilters',[]).filter('unique', function() {
return function(data, propertyname) {
if (angular.isArray(data) && angular.isString(propertyname)) {
var results = [];
var keys = {};
for (var i = 0; i < data.length; i++) {
var val = data[i][propertyname];
if (angular.isUndefined(keys[val])) {
keys[val] = true;
results.push(val);
}
}
return results;
} else {
return data;
}
}
});
sportsStore.js file
//declaring a dependency called customFilters that contains a unqiue filter
angular.module('sportsStore',['customFilters']);
// calling the angular.module method passing in sportsStore located in app.html
angular.module('sportsStore').controller('sportsStoreCtrl', function($scope) {
$scope.data = {
products: [
{name: "Product 1", description:"A product", category:"Category #1", price: 100},
{name: "Product 2", description:"A product", category:"Category #1", price: 110},
{name: "Product 3", description:"A product", category:"Category #2", price: 210},
{name: "Product 4", description:"A product", category:"Category #3", price: 202}
]
};
});
my productListControllers.js file
angular.module('sportsStore').controller('productListCtrl', function($scope,$filter){
var selectedCategory = null;
$scope.selectedCategory = function(newCategory) {
selectedCategory = newCategory;
};
$scope.categoryFilterFn = function(product) {
return selectedCategory == null || product.category == selectedCategory;
};
});
app.html file
<!DOCTYPE html>
<!-- We are defining the sportStore module here in the html tag-->
<html ng-app="sportsStore">
<head>
<title>Sports Store</title>
<link href="bootstrap.min.css" rel="stylesheet" />
<link href="bootstrap-theme.min.css" rel="stylesheet" />
</head>
<!-- Applying ng-controller to the body tagg -->
<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">Sports Store</a>
</div>
<div class="panel panel-default row" ng-controller="productListCtrl">
<div class="col-xs-3">
<a class="btn btn-block btn-default btn-lg" ng-click="selectCategory()">Home</a>
<!-- generating the navigation elements here -->
<a class="btn btn-block btn-default btn-lg" ng-repeat="item in data.products |orderBy:'category'| unique:'category'" ng-click="selectCategory(item)">{{item}}</a>
</div>
<div class="col-xs-8">
<!-- ng-repeat generates elements for each object in an array -->
<!-- we also create a local variable called item -->
<div class="well" ng-repeat="item in data.products | filter:categoryFilterFn">
<h3>
<strong>{{item.name}}</strong>
<span class="pull-right label label-primary">{{item.price | currency}}</span>
</h3>
<span class="lead">{{item.description}}</span>
</div>
</div>
</div>
<script src="angular.js"></script>
<script src="controllers/sportsStore.js"></script>
<script src="filters/customFilters.js"></script>
<script src="controllers/productListControllers.js"></script>
</body>
</html>
You have a typo in your html file. The function is selectedCategory not selectCategory.
There is a typo, the template says selectCategory and the controller says selectedCategory
Related
im struggling with iterating over arrays in arrays. I need to create buttonlike vertical menu and cant get it work.
angular.module('NavigationApp',[]).controller('NavigationController', function($scope) {
$scope.items = [
'Home',
'Orders':
{
orders:['Orders', 'Open', 'Closed', 'New', 'Forgotten']
},
'Users',
'Resources',
'Settings',
'Help'
];
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items | filter:filterQuery">{{ item }}
</li>
</ul>
</div>
</div>
<script src="js/MainController.js"></script>
</body>
</html>
What i need to do is display array of items and while Orders item is active expand it with elements given in other array. To be honest i just dont know how to make it.
You are trying to ng-repeat over a heterogeneus array. i.e. it's elements are not all of the same type. The implementation logic needs to change here.
One thing you can do if your data structure is not flexible, is to use a typeof item === 'object' to filter out the object from the strings, or conversely check for typeof string
Here's a quick, basic example of what you could use:
$scope.items = [{
name: 'Home'
}, {
name: 'Orders',
dropdown: [{
name: 'Orders'
}]
},{
name: 'Users'
},
...
];
<li ng-repeat="item in items | filter:filterQuery" class="btn btn-lg list-group-item dropdown" ng-class="{active: activeMenu === item}" ng-click="setActive(item)">
<a aria-expanded="false" aria-haspopup="true" role="button" data-toggle="dropdown" class="dropdown-toggle" href="#">
{{ item.name }} <span class="caret" ng-if="item.dropdown"></span>
</a>
<ul ng-if="item.dropdown" class="dropdown-menu">
<li ng-repeat="dItem in item.dropdown">
{{dItem.name}}
</li>
</ul>
</li>
I'd suggest having another indepth look at https://docs.angularjs.org/api/ng/directive/ngRepeat to fully understand the structure required by the directive.
angular.module('NavigationApp',[]).controller('NavigationController', function($scope) {
$scope.items = {
main:['Home','Orders','Users','Resources','Settings','Help'],
sub:['Open','Closed','New','Forgotten']
};
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items.main | filter:filterQuery">{{ item }}
<ul>
<li class="btn btn-lg list-group-item" ng-repeat="it in items.sub" ng-if="activeMenu === 'Orders'">{{it}}</li>
</ul>
</li>
</ul>
</div>
</div>
<script src="js/MainController.js"></script>
</body>
</html>
This is closer to what i want to achieve. But i dont know how to apply this nested UL to only one Li from parent list.
this filter work correctly
INPUT :
['Home',{ 'Orders':{orders:['Orders', 'Open', 'Closed', 'New', 'Forgotten']}},'Users','Resources','Settings','Help']
OUTPUT :
["Home", "Orders", "Open", "Closed", "New", "Forgotten", "Users", "Resources", "Settings", "Help"]
app.filter('customfilter', function () {
return function (data) {
function clean(item)
{
var result = [] ;
// check if type is array
if(Array.isArray(item)){
// parse array
item.forEach(function(i){
result = result.concat(clean(i));
})
}// check if type is opject
else if(typeof item =="object"){
// parse opject
Object.keys(item).map(function (key) {
result = result.concat(clean(item[key]));
});
}else{
result= [item]
}
return result ;
}
return clean(data) ;
}
})
I believe there are so many ways to answer this question,although I've made a sample plunker for your problem.Below is how your
HTML will look like
<body ng-app="NavigationApp">
<div class="col-md-3">
<div ng-controller="NavigationController">
<input type="text" placeholder="Search" ng-model="filterQuery" />
<ul class="list-group">
<li ng-click="setActive(item)" ng-class="{active: activeMenu === item}" class="btn btn-lg list-group-item" ng-repeat="item in items | filter:filterQuery">
<a href="#">
<p ng-hide="item.dropdown"> {{ item.name }}</p>
<p ng-show="item.dropdown" ng-repeat="values in item.dropdown"> {{ values }}</p>
</a>
</li>
</ul>
</div>
</div>
</body>
JS look like
angular.module('NavigationApp', []).controller('NavigationController', function($scope) {
var orderItemsObj = {
orders: ['Orders', 'Open', 'Closed', 'New', 'Forgotten']
};
$scope.items = [{
name: 'Home'
}, {
name: 'Orders',
dropdown: ['Orders', 'Open', 'Closed', 'New', 'Forgotten']
}, {
name: 'Users'
}, ];
$scope.activeMenu = $scope.items[0];
$scope.setActive = function(item) {
$scope.activeMenu = item;
};
});
I have just started learning Angular JS and created some basic samples however I am stuck with the following problem.
I have created 2 modules and 2 controllers.
shoppingCart -> ShoppingCartController
namesList -> NamesController
There are associated views for each controller. The first View renders fine but second is not rendering. There are no errors.
http://jsfiddle.net/ep2sQ/
Please help me solve this issue.
Also is there any possibility to add console in View to check what values are passed from Controller.
e.g. in the following div can we add console.log and output the controller values
<div ng-app="shoppingCart" ng-controller="ShoppingCartController">
</div>
So basically as mentioned by Cherniv we need to bootstrap the modules to have multiple ng-app within the same page. Many thanks for all the inputs.
var shoppingCartModule = angular.module("shoppingCart", [])
shoppingCartModule.controller("ShoppingCartController",
function($scope) {
$scope.items = [{
product_name: "Product 1",
price: 50
}, {
product_name: "Product 2",
price: 20
}, {
product_name: "Product 3",
price: 180
}];
$scope.remove = function(index) {
$scope.items.splice(index, 1);
}
}
);
var namesModule = angular.module("namesList", [])
namesModule.controller("NamesController",
function($scope) {
$scope.names = [{
username: "Nitin"
}, {
username: "Mukesh"
}];
}
);
angular.bootstrap(document.getElementById("App2"), ['namesList']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<div id="App1" ng-app="shoppingCart" ng-controller="ShoppingCartController">
<h1>Your order</h1>
<div ng-repeat="item in items">
<span>{{item.product_name}}</span>
<span>{{item.price | currency}}</span>
<button ng-click="remove($index);">Remove</button>
</div>
</div>
<div id="App2" ng-app="namesList" ng-controller="NamesController">
<h1>List of Names</h1>
<div ng-repeat="_name in names">
<p>{{_name.username}}</p>
</div>
</div>
To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap()
HTML
<!-- Automatic Initialization -->
<div ng-app="myFirstModule">
...
</div>
<!-- Need To Manually Bootstrap All Other Modules -->
<div id="module2">
...
</div>
JS
angular.
bootstrap(document.getElementById("module2"), ['mySecondModule']);
The reason for this is that only one AngularJS application can be automatically bootstrapped per HTML document. The first ng-app found in the document will be used to define the root element to auto-bootstrap as an application.
In other words, while it is technically possible to have several applications per page, only one ng-app directive will be automatically instantiated and initialized by the Angular framework.
You can use angular.bootstrap() directly... the problem is you lose the benefits of directives.
First you need to get a reference to the HTML element in order to bootstrap it, which means your code is now coupled to your HTML.
Secondly the association between the two is not as apparent. With ngApp you can clearly see what HTML is associated with what module and you know where to look for that information. But angular.bootstrap() could be invoked from anywhere in your code.
If you are going to do it at all the best way would be by using a directive. Which is what I did. It's called ngModule. Here is what your code would look like using it:
<!DOCTYPE html>
<html>
<head>
<script src="angular.js"></script>
<script src="angular.ng-modules.js"></script>
<script>
var moduleA = angular.module("MyModuleA", []);
moduleA.controller("MyControllerA", function($scope) {
$scope.name = "Bob A";
});
var moduleB = angular.module("MyModuleB", []);
moduleB.controller("MyControllerB", function($scope) {
$scope.name = "Steve B";
});
</script>
</head>
<body>
<div ng-modules="MyModuleA, MyModuleB">
<h1>Module A, B</h1>
<div ng-controller="MyControllerA">
{{name}}
</div>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
<div ng-module="MyModuleB">
<h1>Just Module B</h1>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
</body>
</html>
You can get the source code for it at:
http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/
It's implemented in the same way as ngApp. It simply calls angular.bootstrap() behind the scenes.
In my case I had to wrap the bootstrapping of my second app in angular.element(document).ready for it to work:
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById("app2"), ["app2"]);
});
Here's an example of two applications in one html page and two conrollers in one application :
<div ng-app = "myapp">
<div ng-controller = "C1" id="D1">
<h2>controller 1 in app 1 <span id="titre">{{s1.title}}</span> !</h2>
</div>
<div ng-controller = "C2" id="D2">
<h2>controller 2 in app 1 <span id="titre">{{s2.valeur}}</span> !</h2>
</div>
</div>
<script>
var A1 = angular.module("myapp", [])
A1.controller("C1", function($scope) {
$scope.s1 = {};
$scope.s1.title = "Titre 1";
});
A1.controller("C2", function($scope) {
$scope.s2 = {};
$scope.s2.valeur = "Valeur 2";
});
</script>
<div ng-app="toapp" ng-controller="C1" id="App2">
<br>controller 1 in app 2
<br>First Name: <input type = "text" ng-model = "student.firstName">
<br>Last Name : <input type="text" ng-model="student.lastName">
<br>Hello : {{student.fullName()}}
<br>
</div>
<script>
var A2 = angular.module("toapp", []);
A2.controller("C1", function($scope) {
$scope.student={
firstName:"M",
lastName:"E",
fullName:function(){
var so=$scope.student;
return so.firstName+" "+so.lastName;
}
};
});
angular.bootstrap(document.getElementById("App2"), ['toapp']);
</script>
<style>
#titre{color:red;}
#D1{ background-color:gray; width:50%; height:20%;}
#D2{ background-color:yellow; width:50%; height:20%;}
input{ font-weight: bold; }
</style>
You can merge multiple modules in one rootModule , and assign that module as
ng-app to a superior element ex: body tag.
code ex:
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="namesController.js"></script>
<script src="myController.js"></script>
<script>var rootApp = angular.module('rootApp', ['myApp1','myApp2'])</script>
<body ng-app="rootApp">
<div ng-app="myApp1" ng-controller="myCtrl" >
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>
<div ng-app="myApp2" ng-controller="namesCtrl">
<ul>
<li ng-bind="first">{{first}}
</li>
</ul>
</div>
</body>
</html>
var shoppingCartModule = angular.module("shoppingCart", [])
shoppingCartModule.controller("ShoppingCartController",
function($scope) {
$scope.items = [{
product_name: "Product 1",
price: 50
}, {
product_name: "Product 2",
price: 20
}, {
product_name: "Product 3",
price: 180
}];
$scope.remove = function(index) {
$scope.items.splice(index, 1);
}
}
);
var namesModule = angular.module("namesList", [])
namesModule.controller("NamesController",
function($scope) {
$scope.names = [{
username: "Nitin"
}, {
username: "Mukesh"
}];
}
);
var namesModule = angular.module("namesList2", [])
namesModule.controller("NamesController",
function($scope) {
$scope.names = [{
username: "Nitin"
}, {
username: "Mukesh"
}];
}
);
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById("App2"), ['namesList']);
angular.bootstrap(document.getElementById("App3"), ['namesList2']);
});
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body>
<div id="App1" ng-app="shoppingCart" ng-controller="ShoppingCartController">
<h1>Your order</h1>
<div ng-repeat="item in items">
<span>{{item.product_name}}</span>
<span>{{item.price | currency}}</span>
<button ng-click="remove($index);">Remove</button>
</div>
</div>
<div id="App2" ng-app="namesList" ng-controller="NamesController">
<h1>List of Names</h1>
<div ng-repeat="_name in names">
<p>{{_name.username}}</p>
</div>
</div>
<div id="App3" ng-app="namesList2" ng-controller="NamesController">
<h1>List of Names</h1>
<div ng-repeat="_name in names">
<p>{{_name.username}}</p>
</div>
</div>
</body>
</html>
// root-app
const rootApp = angular.module('root-app', ['app1', 'app2E']);
// app1
const app11aa = angular.module('app1', []);
app11aa.controller('main', function($scope) {
$scope.msg = 'App 1';
});
// app2
const app2 = angular.module('app2E', []);
app2.controller('mainB', function($scope) {
$scope.msg = 'App 2';
});
// bootstrap
angular.bootstrap(document.querySelector('#app1a'), ['app1']);
angular.bootstrap(document.querySelector('#app2b'), ['app2E']);
<!-- angularjs#1.7.0 -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.min.js"></script>
<!-- root-app -->
<div ng-app="root-app">
<!-- app1 -->
<div id="app1a">
<div ng-controller="main">
{{msg}}
</div>
</div>
<!-- app2 -->
<div id="app2b">
<div ng-controller="mainB">
{{msg}}
</div>
</div>
</div>
Only one app is automatically initialized. Others have to manually initialized as follows:
Syntax:
angular.bootstrap(element, [modules]);
Example:
<!DOCTYPE html>
<html>
<head>
<script src="https://code.angularjs.org/1.5.8/angular.js" data-semver="1.5.8" data-require="angular.js#1.5.8"></script>
<script data-require="ui-router#0.2.18" data-semver="0.2.18" src="//cdn.rawgit.com/angular-ui/ui-router/0.2.18/release/angular-ui-router.js"></script>
<link rel="stylesheet" href="style.css" />
<script>
var parentApp = angular.module('parentApp', [])
.controller('MainParentCtrl', function($scope) {
$scope.name = 'universe';
});
var childApp = angular.module('childApp', ['parentApp'])
.controller('MainChildCtrl', function($scope) {
$scope.name = 'world';
});
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById('childApp'), ['childApp']);
});
</script>
</head>
<body>
<div id="childApp">
<div ng-controller="MainParentCtrl">
Hello {{name}} !
<div>
<div ng-controller="MainChildCtrl">
Hello {{name}} !
</div>
</div>
</div>
</div>
</body>
</html>
AngularJS API
You can define a Root ng-App and in this ng-App you can define multiple nd-Controler. Like this
<!DOCTYPE html>
<html>
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
<style>
table, th , td {
border: 1px solid grey;
border-collapse: collapse;
padding: 5px;
}
table tr:nth-child(odd) {
background-color: #f2f2f2;
}
table tr:nth-child(even) {
background-color: #ffffff;
}
</style>
<script>
var mainApp = angular.module("mainApp", []);
mainApp.controller('studentController1', function ($scope) {
$scope.student = {
firstName: "MUKESH",
lastName: "Paswan",
fullName: function () {
var studentObject;
studentObject = $scope.student;
return studentObject.firstName + " " + studentObject.lastName;
}
};
});
mainApp.controller('studentController2', function ($scope) {
$scope.student = {
firstName: "Mahesh",
lastName: "Parashar",
fees: 500,
subjects: [
{ name: 'Physics', marks: 70 },
{ name: 'Chemistry', marks: 80 },
{ name: 'Math', marks: 65 },
{ name: 'English', marks: 75 },
{ name: 'Hindi', marks: 67 }
],
fullName: function () {
var studentObject;
studentObject = $scope.student;
return studentObject.firstName + " " + studentObject.lastName;
}
};
});
</script>
<body>
<div ng-app = "mainApp">
<div id="dv1" ng-controller = "studentController1">
Enter first name: <input type = "text" ng-model = "student.firstName"><br/><br/> Enter last name: <input type = "text" ng-model = "student.lastName"><br/>
<br/>
You are entering: {{student.fullName()}}
</div>
<div id="dv2" ng-controller = "studentController2">
<table border = "0">
<tr>
<td>Enter first name:</td>
<td><input type = "text" ng-model = "student.firstName"></td>
</tr>
<tr>
<td>Enter last name: </td>
<td>
<input type = "text" ng-model = "student.lastName">
</td>
</tr>
<tr>
<td>Name: </td>
<td>{{student.fullName()}}</td>
</tr>
<tr>
<td>Subject:</td>
<td>
<table>
<tr>
<th>Name</th>.
<th>Marks</th>
</tr>
<tr ng-repeat = "subject in student.subjects">
<td>{{ subject.name }}</td>
<td>{{ subject.marks }}</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>
I have modified your jsfiddle, can make top most module as rootModule for rest of the modules.
Below Modifications updated on your jsfiddle.
Second Module can injected in RootModule.
In Html second defined ng-app placed inside the Root ng-app.
Updated JsFiddle:
http://jsfiddle.net/ep2sQ/1011/
Use angular.bootstrap(element, [modules], [config]) to manually start up AngularJS application (for more information, see the Bootstrap guide).
See the following example:
// root-app
const rootApp = angular.module('root-app', ['app1', 'app2']);
// app1
const app1 = angular.module('app1', []);
app1.controller('main', function($scope) {
$scope.msg = 'App 1';
});
// app2
const app2 = angular.module('app2', []);
app2.controller('main', function($scope) {
$scope.msg = 'App 2';
});
// bootstrap
angular.bootstrap(document.querySelector('#app1'), ['app1']);
angular.bootstrap(document.querySelector('#app2'), ['app2']);
<!-- angularjs#1.7.0 -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.min.js"></script>
<!-- root-app -->
<div ng-app="root-app">
<!-- app1 -->
<div id="app1">
<div ng-controller="main">
{{msg}}
</div>
</div>
<!-- app2 -->
<div id="app2">
<div ng-controller="main">
{{msg}}
</div>
</div>
</div>
<html>
<head>
<script src="angular.min.js"></script>
</head>
<body>
<div ng-app="shoppingCartParentModule" >
<div ng-controller="ShoppingCartController">
<h1>Your order</h1>
<div ng-repeat="item in items">
<span>{{item.product_name}}</span>
<span>{{item.price | currency}}</span>
<button ng-click="remove($index);">Remove</button>
</div>
</div>
<div ng-controller="NamesController">
<h1>List of Names</h1>
<div ng-repeat="name in names">
<p>{{name.username}}</p>
</div>
</div>
</div>
</body>
<script>
var shoppingCartModule = angular.module("shoppingCart", [])
shoppingCartModule.controller("ShoppingCartController",
function($scope) {
$scope.items = [
{product_name: "Product 1", price: 50},
{product_name: "Product 2", price: 20},
{product_name: "Product 3", price: 180}
];
$scope.remove = function(index) {
$scope.items.splice(index, 1);
}
}
);
var namesModule = angular.module("namesList", [])
namesModule.controller("NamesController",
function($scope) {
$scope.names = [
{username: "Nitin"},
{username: "Mukesh"}
];
}
);
angular.module("shoppingCartParentModule",["shoppingCart","namesList"])
</script>
</html>
I have the following Javascript that I am using to make a sort of flowchart where the user clicks through a set of questions. For certain responses i want to link to an external site where more info can be found. How do I add these links?
HTML
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="row">
<div class="col-xs-12 text-right">
<button class="btn btn-default btn-corner" type="submit" data-bind="click: startOver, visible: queryData().id > 0">Start over</button>
</div>
</div>
</div>
<div class="container main">
<div class="row">
<div class="c12 text-center">
<h1 data-bind="text: queryData().text"></h1>
<h3 data-bind="text: queryData().subhead"></h3>
<div class="option-group" data-bind="foreach: queryData().answers">
<button class="btn btn-default btn-lg" type="submit" data-bind="click: $parent.goToTarget, text: text"></button>
</div>
<button class="btn btn-default" type="submit" data-bind="click: stepBack, visible: navHistory().length > 1">Previous Step</button>
</div>
</div>
</div>
<div class="push"></div>
</div>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
<script src="app.js?v=0.4.0"></script>
<script>
</script>
</body>
</html>
The Javascript is as follows:
JS
var queries = [{
id: 0,
text: "Where to start?",
answers: [{
text: "Let's Begin!",
target: 1
}]
}, {
id: 1,
text: "Which genre do you want to start in?",
answers: [{
text: "Fantasy",
target: 100
}, {
text: "SciFi",
target: 2
}, {
text: "Neither",
target: 59
}]
}, {
id: 2,
text: "It's huge but it's worth it. The Cryptonomicon by Neal Stephenson",
answers: [{
text: "Amazon.co.uk",
target: "_blank"
}, {
text: "Amazon.com"
}]
}];
function QueryViewModel() {
var self = this;
self.querySet = ko.observable();
self.currentStep = ko.observable();
self.queryData = ko.observable();
self.sfw = ko.observable();
self.navHistory = ko.observableArray();
// Operations
self.goToTarget = function(obj) {
self.navHistory.push(self.currentStep());
self.currentStep(obj.target);
self.queryData(self.querySet()[obj.target]);
}
self.startOver = function() {
self.navHistory.removeAll();
self.goToTarget({target: 0});
}
self.stepBack = function() {
var lastStep = self.navHistory().length > 1 ? self.navHistory.pop() : 0;
self.currentStep(lastStep);
self.queryData(self.querySet()[lastStep]);
}
var paramsString = document.location.hash.substring(1);
var params = new Array();
if (paramsString) {
var paramValues = paramsString.split("&");
for (var i = 0; i < paramValues.length; i++) {
var paramValue = paramValues[i].split("=");
params[paramValue[0]] = paramValue[1];
}
}
params ? paramTarget = params['target'] : params = [];
self.sfw() ? self.querySet(queriesSFW) : self.querySet(queries);
if (paramTarget) {
self.navHistory.push(0);
self.currentStep(0);
self.goToTarget({target: paramTarget})
} else {
self.goToTarget({target: 0});
}
}
ko.applyBindings(new QueryViewModel());
In html you can do something like this:
<button type="button" onclick="window.open('https://google.com/', '_self')">Button</button>
You don't have to use a button, different elements can use onclick like text or images. This can also call js functions, just put the function name where "window.open..." is.
Of course the standard way to do it is
<a href='https://www.google.com/'>Link</a>
You can practice using js here: http://www.w3schools.com/js/tryit.asp?filename=tryjs_intro_inner_html
and learn more about it here: http://www.w3schools.com/js/js_intro.asp
I am not sure why you would show us the JSON for open a link to another page. Unless I misunderstood. This kind of basic information can be found by a quick Google search.
Add your link in the object like:
text: "Fantasy",
link: "http://www.stackoverflow.com",
target: 2
Now when you need to go to that link, use this function:
var link = obj.link;
window.open(link, "_blank");
I have written the following HTML & AngularJS code to update the Tree on HTML Page (View) on the Click of a Button.
When the Button is clicked, the changes appear for a fraction of second and disappear. I am not able to find the reason for this. Could you please let me know how I can overcome this problem?
Below is the HTML and JS Code. This is working in the Snippet Editor, but not in the Browser.
var module = angular.module('myapp', []);
module.controller("TreeCtrl", function($scope) {
$scope.categories = [];
$scope.$apply($scope.addTreeToView = function() {
$scope.categories = [{
title: 'Computers1',
categories: [{
title: 'Laptops1',
categories: [{
title: 'Ultrabooks1'
}, {
title: 'Macbooks1'
}]
}, {
title: 'Desktops1'
}, {
title: 'Tablets1',
categories: [{
title: 'Apple1'
}, {
title: 'Android1'
}]
}]
}, {
title: 'Printers1',
categories: [{
title: 'HP1'
}, {
title: 'IBM1'
}]
}];
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<title>Tree Example</title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
</head>
<body>
<div ng-app="myapp">
<div class="col-sm-10 col-sm-offset-1" ng-controller="TreeCtrl">
<form action="#" method="post" class="form-horizontal" id="commentForm" role="form">
<div class="form-group" id="div_submitComment">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success btn-circle text-uppercase" type="submit" ng-click="addTreeToView()"><span class="glyphicon glyphicon-send" id="qazwsx"></span> Create Tree</button>
</div>
</div>
</form>
<div class="page-header">
<h3 class="reviews">Tree</h3>
</div>
<script type="text/ng-template" id="categoryTree">
{{ category.title }}
<ul ng-if="category.categories">
<li ng-repeat="category in category.categories" ng-include="'categoryTree'">
</li>
</ul>
</script>
<ul>
<li ng-repeat="category in categories" ng-include="'categoryTree'"></li>
</ul>
</div>
</div>
<script src="self.js"></script>
</body>
try removing type="submit" from the buttom
I was using Form element type of Bootstrap. This has an action attribute. I removed the action attribute. Code works fine after removing it
< form method = "post"
class = "form-horizontal"
id = "commentForm"
role = "form" >
< div class = "form-group"
id = "div_submitComment" >
< div class = "col-sm-offset-2 col-sm-10" >
< button class = "btn btn-success btn-circle text-uppercase"
type = "submit"
ng - click = "addTreeToView()" > < span class = "glyphicon glyphicon-send"
id = "qazwsx" > < /span> Create Tree</button >
< /div>
</div >
< /form>
Because your html will be reloaded after you do "submit" action.So you have to replace "type="submit" by type="button" and disable "auto submit".
I want to use angular-drag-and-drop-lists with my own grid template to WYSIWYG editor. How to build my own HTML template without ng-repeat so it will be able to drop items in any predefined column and store information in $scope in which column item has been dropped?
I want to store dropped items in columns array:
.controller('DragDropGrid', ['$scope',
function($scope) {
$scope.layouts = {
selected: null,
templates: [
{name: "Plugin", type: "item", id: 2},
],
columns: [],
oldaproachcolumns: [
"A": [
],
"B": [
]
}
]
};
}
]);
This is currently not a working template. On drop it throws the error "undefined is not an object (evaluating 'targetArray.splice')":
<div ng-include="'grid.html'"></div>
<script type="text/ng-template" id="grid.html">
<div class="col-md-12 dropzone box box-yellow">
<div class="row template-grid" dnd-list="list">
<div class="col-xs-12 col-md-8" ng-repeat="item in list" dnd-draggable="item" ng-include="item.type + '.html'">Header</div>
<div class="col-xs-6 col-md-4">News</div>
</div>
</div>
</script>
<script type="text/ng-template" id="item.html">
<div class="item">Plugin {{item.id}}</div>
</script>
This is the standard working aproach:
<div class="row">
<div ng-repeat="(zone, list) in layouts.oldaproachcolumns" class="col-md-3">
<div class="dropzone box box-yellow">
<h3>{{zone}}</h3>
<div ng-include="'list.html'"></div>
</div>
</div>
</div>
<script type="text/ng-template" id="list.html">
<ul dnd-list="list">
<li ng-repeat="item in list" dnd-draggable="item" dnd-effect-allowed="move" dnd-moved="list.splice($index, 1)" dnd-selected="layouts.selected = item" ng-class="{selected: layouts.selected === item}" ng-include="item.type + '.html'">
</li>
</ul>
</script>
Based on this example: demo
How to build my own HTML template without ng-repeat
Use $templateCache and a for loop as an alternative:
var app = angular.module('foo', []);
function bop(model, data)
{
return data ? model : 'foo';
}
function baz()
{
return bop;
}
function foo($templateCache)
{
var i = 0, len = 5, bar = "";
for (i; i < len; i++)
{
bar = bar.concat("<li>",i,"<p ng-include=\u0022'foo'\u0022></p></li>");
}
$templateCache.put('listContent', bar);
}
angular.module('foo').filter('baz', baz);
app.run(foo);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="foo">
<script type="text/ng-template" id="foo">
<span>hi</span>
</script>
<input ng-model="dude">
<ul ng-include="'listContent' | baz:dude"></ul>
</div>
References
AngularJS: API: $templateCache
AngularJS: Is there a better way to achieve this than the one specified?