Uncaught ReferenceError: $scope is not defined - javascript

Receiving the error when the page is loaded. I'm trying to append a new object to an array of entries.
What is wrong with the code?
index.html
Raffler
<div ng-controller="RaffleCtrl">
<form ng-sumbit="addEntry">
<input type="text" ng-model="newEntry.name">
<input type="submit" value="Add">
</form>
<ul>
<li ng-repeat="entry in entries">{{entry.name}}</li>
</ul>
</div>
raffle.js
angular.module('myApp', []).controller("RaffleCtrl", function ($scope) {
$scope.entries = [
{
name: "Larry"
}, {
name: "Curly"
}, {
name: "Moe"
}
]
});
$scope.addEntry = function () {
$scope.entries($scope.newEntry)
$scope.newEntry = {}
};

You wrongly used $scope outside the controller. Use the $scope inside the controller
angular.module('myApp', []).controller("RaffleCtrl", function ($scope) {
$scope.entries = [
{
name: "Larry"
}, {
name: "Curly"
}, {
name: "Moe"
}
];
$scope.addEntry = function () {
$scope.entries($scope.newEntry)
$scope.newEntry = {}
};
});

if you really want to keep it outside
angular.module('myApp', []).controller("RaffleCtrl", function ($scope) {
$scope.entries = [
{
name: "Larry"
}, {
name: "Curly"
}, {
name: "Moe"
}
];
$scope.addEntry = addEntry;
});
function addEntry() {
$scope.entries($scope.newEntry)
$scope.newEntry = {}
};

Related

Rendering a table in Angular 1 without ng-repeat

I'm trying to find a better way for rendering a large table in Angular than using ngRepeat.
I tried using one-time {{::binding}}s, but found the initial render time remained unchanged, which wasn't satisfactory.
Back to the drawing board, I'm trying to find a much more performant method for assembling data into a HTML table in the DOM. I've been trying to use angular.element() to assemble all the parts into a whole, but with no luck. Any insights?
var app = angular.module('app', []);
app.directive('myTable', function() {
return {
restrict: 'E',
scope: {
ngModel: "=",
},
require: 'ngModel',
link: function(scope, element, attrs) {
scope.$watch('ngModel', function() {
if (typeof scope.ngModel == 'undefined') {
console.log("ngModel not defined yet");
return;
}
element.html('');
var table = angular.element('<table/>');
var tbody = angular.element('<tbody/>');
scope.ngModel.forEach(function(m) {
var tr = angular.element('<tr/>');
m.fields.forEach(function(f) {
var td = angular.element('<td/>')
td.text(f.value);
td.append(tr);
});
tr.append(tbody);
})
tbody.append(table);
table.append(element);
})
}
}
});
app.controller('AppController', function($scope) {
$scope.data = [{
fields: [{
value: 1,
metadata: ""
}, {
value: 2,
metadata: ""
}, {
value: 3,
metadata: ""
}, {
value: 4,
metadata: ""
}, {
value: 5,
metadata: ""
}, ]
},
{
fields: [{
value: 6,
metadata: ""
}, {
value: 7,
metadata: ""
}, {
value: 8,
metadata: ""
}, {
value: 9,
metadata: ""
}, {
value: 10,
metadata: ""
}, ]
}
]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="app" ng-controller="AppController">
<my-table ng-model="data"></my-table>
</div>
</body>
It is inappropriate to involve the ngModel controller in a directive that has no user input elements. Also isolate scope is unnecessary. Evaluate the table-data attribute in the watch expression.
Also of course, fix the backwards append statements:
app.directive('myTable', function() {
return {
restrict: 'E',
̶s̶c̶o̶p̶e̶:̶ ̶{̶
̶n̶g̶M̶o̶d̶e̶l̶:̶ ̶"̶=̶"̶,̶
̶}̶,̶
̶r̶e̶q̶u̶i̶r̶e̶:̶ ̶'̶n̶g̶M̶o̶d̶e̶l̶'̶,̶
link: function(scope, element, attrs) {
scope.$watch(attrs.tableData ̶'̶n̶g̶M̶o̶d̶e̶l̶'̶, function(data) {
if (data) {
console.log("table-data not defined yet");
return;
}
element.html('');
var table = angular.element('<table/>');
var tbody = angular.element('<tbody/>');
data.forEach(function(m) {
var tr = angular.element('<tr/>');
m.fields.forEach(function(f) {
var td = angular.element('<td/>')
td.text(f.value);
̶t̶d̶.̶a̶p̶p̶e̶n̶d̶(̶t̶r̶)̶;̶ tr.append(td);
});
̶t̶r̶.̶a̶p̶p̶e̶n̶d̶(̶t̶b̶o̶d̶y̶)̶;̶ tbody.append(tr);
})
̶t̶b̶o̶d̶y̶.̶a̶p̶p̶e̶n̶d̶(̶t̶a̶b̶l̶e̶)̶;̶ table.append(tbody);
̶t̶a̶b̶l̶e̶.̶a̶p̶p̶e̶n̶d̶(̶e̶l̶e̶m̶e̶n̶t̶)̶;̶ element.append(table);
})
}
}
});
Usage:
<my-table table-data="data"></my-table>
THE DEMO
var app = angular.module('app', []);
app.directive('myTable', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
scope.$watch(attrs.tableData, function(data) {
console.log(data);
if (!data) {
console.log("tableData not defined yet");
return;
}
element.html('');
var table = angular.element('<table/>');
var tbody = angular.element('<tbody/>');
data.forEach(function(m) {
var tr = angular.element('<tr/>');
m.fields.forEach(function(f) {
var td = angular.element('<td/>')
td.text(f.value);
tr.append(td);
});
tbody.append(tr);
})
table.append(tbody);
element.append(table);
})
}
}
});
app.controller('ctrl', function($scope) {
$scope.data = [{
fields: [{
value: 1,
metadata: ""
}, {
value: 2,
metadata: ""
}, {
value: 3,
metadata: ""
}, {
value: 4,
metadata: ""
}, {
value: 5,
metadata: ""
}, ]
},
{
fields: [{
value: 6,
metadata: ""
}, {
value: 7,
metadata: ""
}, {
value: 8,
metadata: ""
}, {
value: 9,
metadata: ""
}, {
value: 10,
metadata: ""
}, ]
}
]
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl">
<my-table table-data="data"></my-table>
</body>

selectable table modal popup in angular js

I am trying to open a modal popup with table. How can I do this? In my app.js, on the click event of row open a modal, I also want to update some field with the selected item value. But i can't update with selected value.
my app.js
var tableApp = angular.module('tableApp', ['ui.bootstrap']);
tableApp.controller('tableController', function ($scope,$rootScope, $filter, $modal) {
$scope.filteredPeople = [];
$scope.currentPage = 1;
$scope.pageSize = 10;
$scope.people = [{ id: "1", name: "joe",disable:true },
{ id: "2", name: "bill", disable: true },
{ id: "3", name: "john", disable: true },
{ id: "1", name: "joe", disable: true },
{ id: "2", name: "bill", disable: true },
{ id: "3", name: "john", disable: true },
{ id: "1", name: "joe", disable: true },
{ id: "2", name: "bill", disable: true },
{ id: "3", name: "john", disable: true },
{ id: "1", name: "joe", disable: true },
{ id: "2", name: "bill", disable: true },
{ id: "3", name: "john", disable: true },
{ id: "1", name: "joe" },
{ id: "2", name: "bill", disable: true },
{ id: "3", name: "john", disable: true }];
$scope.getPage = function () {
var begin = (($scope.currentPage - 1) * $scope.pageSize);
var end = begin + $scope.pageSize;
$scope.filteredPeople = $filter('filter')($scope.people, {
id: $scope.idFilter,
name: $scope.nameFilter
});
$scope.totalItems = $scope.filteredPeople.length;
$scope.filteredPeople = $scope.filteredPeople.slice(begin, end);
};
$scope.getPage();
$scope.pageChanged = function () {
$scope.getPage();
};
$scope.open = function () {
$scope.id = generateUUID();
};
$scope.dblclick = function (index) {
for (var i = 0; i < $scope.filteredPeople.length; i++) {
$scope.filteredPeople[i].disable = true;
}
return index.disable = false;
}
$scope.rowSelect = function (rowdata) {
alert(rowdata.name);
}
});
tableApp.controller('DetailModalController', [
'$scope', '$modalInstance', 'item',
function ($scope, $modalInstance, item) {
$scope.item = item;
$scope.dismiss = function () {
$modalInstance.dismiss();
};
$scope.close = function () {
$modalInstance.close($scope.item);
};
}]);
tableApp.directive('myModal', function ($log, $compile) {
var parm = [];
return {
restrict: 'E',
templateUrl: 'modalBase.html',
scope: {
modal: '=',
idF:'='
},
link: function (scope, element, attrs) {
debugger;
parm.name = attrs.idf;
}
//controller: function ($scope) {
// debugger;
// console.log($scope);
// $scope.selected = {
// item: $scope.modal.items[0]
// };
// $scope.ok = function () {
// debugger;
// alert(parm.name);
// $scope.modal.instance.close($scope.selected);
// };
// $scope.cancel = function () {
// $scope.modal.instance.dismiss('cancel');
// };
// $scope.modal.instance.result.then(function (selectedItem) {
// $scope.selected = selectedItem;
// }, function () {
// $log.info('Modal dismissed at: ' + new Date());
// });
//}
};
});
As I understand, you use angular.ui. I would suggesst you to use $modal service instead of $modalInstance. Using that you can call your modal instance with $modal.open(). And also you don't need to close it in your controller - place appropriate methods on your modal template and it will work by its services
Template:
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<ul>
<li ng-repeat="item in items">
{{ item }}
</li>
</ul>
Selected: <b>{{ selected.item }}</b>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="$close()">OK</button>
<button class="btn btn-warning" type="button" ng-click="$dismiss('cancel')">Cancel</button>
</div>
</script>
Controlelr
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
You can find more info about it in angular.ui documentation for modals

Javascript unlimited category depth tree

I am trying to generate a tree of flat array , placing sub categories next to the parent category and having hard doing same.
var categories = [
{
name: 'Javascript'
},
{
name: 'jQuery',
parent: 'Javascript'
},
{
name: 'AngularUi',
parent: 'Angular'
},
{
name: 'Angular',
parent: 'Javascript'
},
{
name: 'D3',
parent: 'Javascript'
}
];
var tree = [];
function getChilds(array,identifier){
return _.filter(array,function(val){
return val.parent == identifier
});
}
function createTree(array){
for(var x=0;x<_.size(array);x++){
tree.push(array[x].name);
var childs = getChilds(array,array[x].name);
if(_.size(childs) > 0){
createTree(childs);
}else{
$('div').append(JSON.stringify(tree));
}
}
}
createTree(categories);
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
Expected Output
['Javascript','Jquery','Angular','AngularUi','D3']
This is what i have tried so far, and using underscore for little help. Any help will be appreciated .
I don't know why you would want to do this (the result you have described is not a tree at all), but the following will provide the result you are describing:
function addChildren(source, identifier, dest) {
source.filter(function(val) {
return val.parent == identifier;
}).forEach(function(val) {
dest.push(val.name);
addChildren(source, val.name, dest);
});
}
function buildTree(source) {
var dest = [];
addChildren(source, undefined, dest);
return dest;
}
var categories = [{
name: 'Javascript'
}, {
name: 'jQuery',
parent: 'Javascript'
}, {
name: 'AngularUi',
parent: 'Angular'
}, {
name: 'Angular',
parent: 'Javascript'
}, {
name: 'D3',
parent: 'Javascript'
}];
var tree = buildTree(categories);
Note that the approach above using filter is an O(N2) operation (it's very inefficient).
You can change it into an O(N) operation by indexing the source arrray first using _.groupBy:
function addChildren(index, identifier, dest) {
(index[identifier] || []).forEach(function (val) {
dest.push(val.name);
addChildren(index, val.name, dest);
});
}
function buildTree(source) {
var dest = [];
addChildren(_.groupBy(source, 'parent'), undefined, dest);
return dest;
}
var categories = [{
name: 'Javascript'
}, {
name: 'jQuery',
parent: 'Javascript'
}, {
name: 'AngularUi',
parent: 'Angular'
}, {
name: 'Angular',
parent: 'Javascript'
}, {
name: 'D3',
parent: 'Javascript'
}];
var tree = buildTree(categories);
console.log(tree);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>

Angularjs: call a controller method with param from a directive dropdown on change event

I have made a dropdown directive. On selecting a value from the dropdown, a method from the controller is called with the selected filter passed. Everything works fine except that the method is always returning the default selected value, no matter, what is selected.
html:
<div ng-controller="Ctrl">
<div>
<dropdown filters="filters" filter="filter" select="selectFilter(filter)"></dropdown>
</div>
</div>
javascript:
var app = angular.module('app', []);
function Ctrl($scope){
$scope.filters = [
{ Id: 1, Name: "All" }, { Id: 2, Name: "filter1" }, { Id: 3, Name: "filter2" }, { Id: 4, Name: "filter3"}
];
$scope.filter = $scope.filters[0];
$scope.selectFilter = function(selectedFilter){
alert(selectedFilter.Name);
};
}
app.directive('dropdown', function(){
return {
restrict: "E",
scope: {
filter: "=",
filters: "=",
select: "&"
},
template: "<select ng-model=\"filter\" ng-change=\"select(filter)\" ng-options=\"f.Name for f in filters\"></select>"
};
});
Working fiddle: http://jsfiddle.net/wXV6Z/98/
You're using wrong syntax to call method binding.
Try:
ng-change=\"select({filter:filter})\
DEMO
I made this, but the other answer seems better :P
http://jsfiddle.net/wXV6Z/101/
var app = angular.module('app', []);
function Ctrl($scope, $element){
$scope.filters = [
{ Id: 1, Name: "All" }, { Id: 2, Name: "filter1" }, { Id: 3, Name: "filter2" }, { Id: 4, Name: "filter3"}
];
$scope.filter = $scope.filters[0];
}
app.directive('dropdown', function(){
return {
restrict: "E",
scope: {
filter: "=",
filters: "=",
},
template: "<select ng-model=\"filter\" ng-change=\"selectFilter(filter)\" ng-options=\"f.Name for f in filters\"></select>",
controller: function($scope, $element) {
$scope.selectFilter = function(selectedFilter) {
alert(selectedFilter.Name);
}
}
}
});

AngularJS : cannot connect factory to controller

I'm sorry if this is an easy question. I'm new and probably don't understand the right things to search for to find the answer.
I've basically followed this angularJS tutorial http://www.youtube.com/watch?v=i9MHigUZKEM
I've gotten through all of it except setting up a factory that connects to my controller.
Here is the code for the factory:
demoApp.factory('simpleFactory', function(){
var people = [
{ name: 'Will', age: '30' },
{ name:'Jack', age:'26' },
{ name: 'Nadine', age: '21' },
{ name:'Zach', age:'28' }
];
var factory = {};
factory.getPeople = function() {
return people;
};
});
Here is the controller:
demoApp.controller('FirstCtrl', ['$scope', 'simpleFactory', function ($scope, simpleFactory) {
$scope.people = simpleFactory.getPeople();
}]);
And just a simple repeat in the HTML:
Name:
<input type="text" ng-model="filter.name"> {{ nameText }}
<ul>
<li ng-repeat="person in people | filter:filter.name | orderBy: 'name'">{{ person.name }}- {{ person.age }}</li>
</ul>
The error I get is "TypeError: Cannot call method 'getPeople' of undefined" in the javascript console.
Note: This all works correctly when within the controller I have the data object hardcoded in like so:
demoApp.controller('FirstCtrl', ['$scope', 'simpleFactory', function ($scope, simpleFactory) {
$scope.people = [
{ name: 'Will', age: '30' },
{ name:'Jack', age:'26' },
{ name: 'Nadine', age: '21' },
{ name:'Zach', age:'28' }
];
}]);
A small change in your service;
demoApp.factory('simpleFactory', function(){
var people = [
{ name: 'Will', age: '30' },
{ name:'Jack', age:'26' },
{ name: 'Nadine', age: '21' },
{ name:'Zach', age:'28' }
];
return {
getPeople: function() {
return people;
};
}
});
And in your controller
demoApp.controller('FirstCtrl', ['$scope', 'simpleFactory', function ($scope, simpleFactory) {
$scope.people = simpleFactory.getPeople();
}]);
Essentially you're just missing the return statement from your 'factory' object, but it might be clearer if you do a little renaming as well to avoid confusion.
Example, adapted from the AngularJS book:
demoApp.factory('People', function(){ // Renamed factory to be more descriptive
var people = {}; // Renamed 'factory' to 'people', as an object we can prototype more functions later
people.query = function() { // called query, but could be getPeople
return [ // just return a static array for now
{ name: 'Will', age: '30' },
{ name:'Jack', age:'26' },
{ name: 'Nadine', age: '21' },
{ name:'Zach', age:'28' }
];
}
return people;
});
So now your controller can pull this information in:
demoApp.controller('FirstCtrl', ['$scope', 'People', function ($scope, People) { // dependency injection
$scope.people = People.query();
});
So now we have a descriptive factory for People that returns an object, one of which is called query. We can later update this query function to read in parameters, fire off AJAX calls and do some complicated stuff. But one step at a time :)

Categories

Resources