I am having issues finding out why the filter is undefined...
Uncaught ReferenceError: filter is not defined(anonymous function) # mainController.js:46(anonymous function) # mainController.js:76
What am I missing?
Index =
<!DOCTYPE html>
<html ng-app="app" ng-open="main.refreshData()">
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="Content/site.css">
<!--<link data-require="ui-grid#*" data-semver="3.0.0RC18" rel="stylesheet" type="text/css" href="Content/ui-grid.css">-->
<link data-require="ui-grid#*" data-semver="3.0.0RC18" rel="stylesheet" href="http://ui-grid.info/release/ui-grid-unstable.css" />
<script src="Scripts/jquery-2.1.4.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Application/app.module.js"></script>
<script src="Application/mainController.js"></script>
<script src="Scripts/ui-grid.min.js"></script>
</head>
<body ng-controller="MainController as main">
<input type="text" ng-model="main.food" placeholder="Enter food" />
<p>Sriracha sauce is great with {{main.food}}!</p>
<br />
<br />
<input type="text" ng-model="main.filterText" ng-change="refreshData()" placeholder="Search..." />
<br />
<br />
<h>{{main.title}}</h>
<div class="grid" ui-grid='main.gridOptions' id="grid1"></div>
</body>
</html>
app =
//The app.module.js file houses a single application-level module for your application.
//In this example, your application has an application-level module that loads the
//other modules of the application. The purpose of adding app.module.js as a separate
//file is to introduce the concept that modules, controllers, services, directives,
//views, etc. should be defined in their own files.
//<<Immediately-invoked function expression>>
//Immediately-invoked function expressions can be used to avoid variable hoisting from
//within blocks, protect against polluting the global environment and simultaneously
//allow public access to methods while retaining privacy for variables defined within the function.
(function () {
'use strict';
angular.module('app', []);
})();
Controller =
(function () {
'use strict';
angular
.module('app', ['ui.grid'])
.controller('MainController', main);
function main() {
var self = this;
self.food = 'pizza';
self.myData = [{
name: "Moroni",
age: 50
}, {
name: "Tiancum",
age: 43
}, {
name: "Jacob",
age: 27
}, {
name: "Nephi",
age: 29
}, {
name: "Enos",
age: 34
}];
self.gridOptions = {
data: "main.myData",
enableGridMenu: true
};
self.title = "ng-grid Example";
self.filterText;
self.refreshData = function () {
self.gridOptions.data = self.filter('filter')(self.myData, self.filterText, undefined);
};
}
//Define a custom filter to search only visible columns (used with grid 3)
filter('visibleColumns', function () {
return function (data, grid, query) {
matches = [];
//no filter defined so bail
if (query === undefined || query === '') {
return data;
}
query = query.toLowerCase();
//loop through data items and visible fields searching for match
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < grid.columnDefs.length; j++) {
var dataItem = data[i];
var fieldName = grid.columnDefs[j]['field'];
//as soon as search term is found, add to match and move to next dataItem
if (dataItem[fieldName].toString().toLowerCase().indexOf(query) > -1) {
matches.push(dataItem);
break;
}
}
}
return matches;
}
});
})();
Translate your filter to function and bind it to application.
angular
.module('app', ['ui.grid'])
.controller('MainController', main)
.filter('visibleColumns', visibleColumns);
function visibleColumns () {...}
There is no function filter(), there is method of angular.module Object that called filter('name', function() { ... }).
More about custom filters
Related
I am creating a simple rest api in javascript, I want upon initialization, the widget must display a list of all characters.
here is folder structure :
├───book
└───book.js
├───store
│ └───store.js
here is my store.js
window.Store = {
create: function() {
var self = {};
var props = {
name: 'string',
species: 'string',
picture: 'string',
description: 'string'
};
var listProps = ['name', 'species'];
var detailProps = ['name', 'species', 'picture', 'description'];
var characters = [
{
id: makeID(),
name: 'Ndiefi',
species: 'Wookie',
picture: 'store/img/ndiefi.png',
description: 'A legendary Wookiee warrior and Han Solo’s co-pilot aboard the Millennium Falcon, Chewbacca was part of a core group of Rebels who restored freedom to the galaxy. Known for his short temper and accuracy with a bowcaster, Chewie also has a big heart -- and is unwavering in his loyalty to his friends. He has stuck with Han through years of turmoil that have changed both the galaxy and their lives.',
_delay: 500
},
];
}
}
here is index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Character Book</title>
<!-- 3rd party vendor libraries -->
<link rel="stylesheet" href="vendor/font-awesome-4.6.3/css/font-awesome.min.css">
<script src="vendor/jquery-3.1.0.min.js"></script>
<script src="vendor/underscore-1.8.3.min.js"></script>
<!-- 1st party internal libraries -->
<script src="store/store.js"></script>
<script src="tests/start-test.js"></script>
<script src="tests/test-book.js"></script>
<!-- The source of the 'Book' widget -->
<link href="book/book.css" rel="stylesheet">
<script src="book/book.js"></script>
<script>
$(function() {
var frame = $('#test-frame');
var run = $('#test-run');
var results = $('#test-results');
var store = Store.create();
run.click(function() {
run.prop('disabled', true).text('Running Tests');
results.removeClass('test-pass test-fail').text('');
testBook(frame).then(
function success() {
run.prop('disabled', false).text('Run Tests');
results.addClass('test-pass').text('All tests passed');
},
function failure(err) {
run.prop('disabled', false).text('Run Tests');
results.addClass('test-fail').text('Test failed, see console');
}
);
});
Book.init(frame, store);
});
</script>
</head>
<body>
<button id="test-run">Run Tests</button>
<span id="test-results"></span>
<div id="test-frame">
</div>
</body>
</html>
here is what I have tried :
books.js
var data = JSON.parse(characters);
data.forEach(characters => {
console.log(characters.name)
});
so when I run the app in my browser I see the following error :
Uncaught ReferenceError: characters is not defined
what is wrong with my code ? any suggestion or help will be helpfull thanks
Backstory: I want to display a little more information on an option element inside of a select box. The way I planned about doing this was to hover over an option and display more information about that option below, and this works! :)
The Problem: While this works in every other browser except IE (I tested this issue in IE11), however, it appears as though IE won't trigger the event at all. I tried different ng-{events} here and nothing appears to work. I want to know if there is a workaround for this, or possibly a different way of solving this problem. I created an example of the issue. Be sure to test it in IE11 (this is the browser I need it to work in unfortunately). Why IE WHYYY!!!? :(
Note I am looking for an angular solution. :)
(function(angular) {
'use strict';
angular.module('ngrepeatSelect', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.data = {
hovered: '',
model: null,
showExtraInformation: function (option) {
this.hovered = option.health;
},
clearExtraInformation: function () {
this.hovered = '';
},
availableOptions: [
{id: '1', name: 'Option A', health: 'Great Health :)'},
{id: '2', name: 'Option B', health: 'Bad Health :('},
{id: '3', name: 'Option C', health: 'Ok Health :|'}
]
};
}]);
})(window.angular);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-select-ngrepeat-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="app.js"></script>
<style>
select {height: 100px; width: 200px;}
</style>
</head>
<body ng-app="ngrepeatSelect">
<div ng-controller="ExampleController">
<form name="myForm">
<label for="repeatSelect"> Repeat select: </label>
<select multiple name="repeatSelect" id="repeatSelect" ng-model="data.model">
<option ng-repeat="option in data.availableOptions"
value="{{option.id}}"
ng-mouseover="data.showExtraInformation(option)"
ng-mouseout="data.clearExtraInformation()">{{option.name}}</option>
</select>
</form>
<hr>
<tt>model = {{data.model}}</tt><br/>
<tt>
hover = {{data.hovered}}
</tt>
</div>
</body>
</html>
In IE 11 blur event is triggered before mousedown , So check if present Element and target element are same then return or else do scroll FUNCTIONALITY something
Inside Blur Event
bind("blur", function(e) {
var tarElement = event.relatedTarget ? event.relatedTarget : nextElement;
if (tarElement.id === iElement.attr('id')) {
return;
} else {
CALL scroll
}
I have an answer...
Underlying Problem: After some reading, IE does not support events on the "option" element. For example, (click, mouseover, mouseout, change, blur, etc).
Based on JC Ford's response, I decided to solve this problem using checkboxes in angular material. I chose not to use a "material multiple select" since the behavior of the UI is not particularly what I or the client is expecting, however, if you wanted to go down that path, I did test it and it does work with these events...
Attached is my solution.
Note: the solution doesn't show the checkboxes, material doesn't want to show up here. Not sure why, but if you put it into your application, it works.
(function(angular) {
'use strict';
angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function($scope) {
$scope.selected = [];
$scope.hovered = '';
$scope.model = null;
$scope.items = [{
id: '1',
name: 'Option A',
health: 'Great Health :)'
},
{
id: '2',
name: 'Option B',
health: 'Bad Health :('
},
{
id: '3',
name: 'Option C',
health: 'Ok Health :|'
}
];
$scope.showExtraInformation = function(option) {
$scope.hovered = option.health;
};
$scope.clearExtraInformation = function() {
$scope.hovered = '';
};
$scope.toggle = function(item, list) {
var idx = list.indexOf(item);
if (idx > -1) {
list.splice(idx, 1);
} else {
list.push(item);
}
};
$scope.exists = function(item, list) {
return list.indexOf(item) > -1;
};
$scope.isIndeterminate = function() {
return ($scope.selected.length !== 0 &&
$scope.selected.length !== $scope.items.length);
};
$scope.isChecked = function() {
return $scope.selected.length === $scope.items.length;
};
$scope.toggleAll = function() {
if ($scope.selected.length === $scope.items.length) {
$scope.selected = [];
} else if ($scope.selected.length === 0 || $scope.items.length > 0) {
$scope.selected = $scope.items.slice(0);
}
};
});
})(window.angular);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-select-ngrepeat-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-route.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>
<script src="//s3-us-west-2.amazonaws.com/s.cdpn.io/t-114/svg-assets-cache.js"></script>
<script src="//cdn.gitcdn.link/cdn/angular/bower-material/v1.1.5/angular-material.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="AppCtrl" class="md-padding demo checkboxdemoSelectAll" ng-app="MyApp">
<fieldset class="demo-fieldset">
<legend class="demo-legend">Using md-checkbox with the 'indeterminate' attribute </legend>
<div layout="row" layout-wrap="" flex="">
<div flex-xs="" flex="50">
<md-checkbox aria-label="Select All" ng-checked="isChecked()" md-indeterminate="isIndeterminate()" ng-click="toggleAll()">
<span ng-if="isChecked()">Un-</span>Select All
</md-checkbox>
</div>
<div class="demo-select-all-checkboxes" flex="100" ng-repeat="item in items">
<md-checkbox ng-checked="exists(item, selected)" ng-click="toggle(item, selected)" ng-mouseover="showExtraInformation(item)" ng-mouseout="clearExtraInformation()">
{{ item.name }}
</md-checkbox>
</div>
</div>
</fieldset>
<hr>
<tt>model = {{selected}}</tt><br/>
<tt>
hover = {{hovered}}
</tt>
</div>
</body>
</html>
I've been writing a code that uses ng-if to display a div with a message if an array is empty([]). The ng-if isn't displaying the div even though I have console.log the array and it shows up empty.
I am still new to angularjs so I am not sure if I am using the ng-if directive correctly. Here is my code, anything helps, thank you!
js:
(function () {
'use strict';
var data = [];
var shoppingList = [
{
name: "Donuts",
quantity: "10"
},
{
name: "Cookies",
quantity: "10"
},
{
name: "Drinks",
quantity: "10"
},
{
name: "Shrimp",
quantity: "10"
},
{
name: "Ice Cream tub",
quantity: "100"
}
];
console.log(data);
angular.module('shoppingListCheckOffApp', [])
.controller('toBuyListController', toBuyListController)
.controller('boughtListController', boughtListController)
.service('shoppingListService', shoppingListService);
toBuyListController.$inject = ['shoppingListService'];
function toBuyListController(shoppingListService) {
var buy = this;
buy.shoppingList = shoppingList;
buy.shoppingListBought = function (itemIndex) {
shoppingListService.dataTransfer(buy.shoppingList[itemIndex].name, buy.shoppingList[itemIndex].quantity);
shoppingListService.remove(itemIndex);
};
}
boughtListController.inject = ['shoppingListService'];
function boughtListController(shoppingListService) {
var bought = this;
bought.data = shoppingListService.getData();
console.log(bought.data);
}
function shoppingListService() {
var service = this;
service.dataTransfer = function (itemName, quantity) {
var item = {
name: itemName,
quantity: quantity
};
data.push(item);
}
service.remove = function (itemIndex) {
shoppingList.splice(itemIndex, 1);
};
service.getData = function () {
return data;
};
};
})();
html:
<!doctype html>
<html ng-app="shoppingListCheckOffApp">
<head>
<title>Shopping List Check Off</title>
<meta charset="utf-8">
<script src="angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div>
<h1>Shopping List Check Off</h1>
<div>
<!-- To Buy List -->
<div ng-controller="toBuyListController as buy">
<h2>To Buy:</h2>
<ul>
<li ng-repeat="item in buy.shoppingList">Buy {{item.quantity}} {{item.name}}(s)<button
ng-click="buy.shoppingListBought($index);" ng-click="myVar = true"><span></span>
Bought</button></li>
</ul>
<div ng-if="buy.shoppingList === []">Everything is bought!</div>
</div>
<!-- Already Bought List -->
<div ng-controller="boughtListController as bought">
<h2>Already Bought:</h2>
<ul>
<li ng-repeat="item in bought.data">Bought {{item.quantity}} {{item.name}}(s)</li>
</ul>
<div ng-if="bought.data === []">Nothing bought yet.</div>
</div>
</div>
</div>
</body>
</html>
You should use ng-if (for arrays) in this way:
<div ng-if="!bought.data.length">Nothing bought yet.</div>
This will show the message when the list is empty.
If you do this:
buy.shoppingList === []
You are comparing you buy.shoppingList array with a new empty array, then it will return false.
I am making an API service with Rotten Tomatoes, and I am unable to see any movies that are being called. When I type in TOY it should return with movie titles that have the word toy within them. But, what I am getting now is grey-outline boxes whenever I search for the movies in my page. How can I make the movies appear on my page correctly? PS sorry for all of this code, it is showing you how my project is working.
Edit: I can't seem to get the slideToggle to work. Please help. Thanks!
Example is in the image:
http://i.stack.imgur.com/Ng0q3.png
Here is my code:
API.html
<div>
<img src="{{movie.posters.thumbnail}}" />
<h2>{{movie.title}}</h2>
</div>
<div>
<p>{{movie.synopsis}}</p>
<dl>
<dt>Rating</dt>
<dd>{{movie.mpaa_rating}}</dd>
<dt>Year</dt>
<dd>{{movie.year}}</dd>
<dt>Critics Score</dt>
<dd>{{movie.ratings.critics_score}}</dd>
<dt>Audience Score</dt>
<dd>{{movie.ratings.audience_score}}</dd>
<dt>Theater Release Date</dt>
<dd>{{movie.release_dates.theater}}</dd>
<dt>DVD Release Date</dt>
<dd>{{movie.release_dates.dvd}}</dd>
</dl>
</div>
apiController.js
module.exports = ApiController;
function ApiController($scope, movieLoader) {
$scope.data = {}
$scope.$watchGroup(['data.q', 'data.page_limit', 'data.page'], function() {
//Use movie loader
movieLoader.getMovies($scope.data.q, $scope.data.page_limit, $scope.data.page).then(function(response) {
$scope.movies = response.data.movies
});
})
}
apiDirective.js
module.exports = function() {
return {
restrict: 'EA',
templateUrl: 'api.html',
link: function(scope, element) {
//Dom manipulation
element.click(function() {
element.children('div').slideToggle();
});
}
};
};
apiFactory.js
module.exports = function apiFactory($http, apiUrl, apiKey) {
//Return object literal
return {
getMovies: function(q, page_limit, page) {
return $http.jsonp(apiUrl, {
params: {
q: q,
page_limit: page_limit,
page: page,
apikey: apiKey,
callback: 'JSON_CALLBACK'
}
});
}
}
}
index.html
<html ng-app="movieApp">
<head>
<title>demo</title>
<script src="bundle.js"></script>
<link href="styles.css" rel="stylesheet">
</head>
<body ng-controller="moviesController">
<!--Grab the title-->
<label for="q">Search Text</label>
<input type="text" id="q" ng-model="data.q" ng-model-options="{debounce: 500}"/>
<!--Define how many movies to place in the file-->
<label for="page_limit">Page Size</label>
<input type="text" id="page_limit" ng-model="data.page_limit" ng-model-options="{debounce: 500}"/>
<!--define what page to look at-->
<label for="page">Page Number</label>
<input type="text" id="page" ng-model="data.page" ng-model-options="{debounce: 500}"/>
<div class="movie" ng-repeat="movie in movies"></div>
</body>
</html>
directiveSearch.html
var jQuery = require('jQuery');
//We must make jquery global for Angular to use it
Window.jQuery = jQuery;
require('angular');
var apiFactory = require('./apiFactory');
var apiController = require('./apiController');
var apiDirective = require('./apiDirective');
angular.module('movieApp', [])
.factory('movieLoader', apiFactory)
.controller('moviesController', apiController)
.directive('movieDirective', apiDirective)
.constant('apiKey', 'Removed for security purposes')
.constant('apiUrl', 'http://api.rottentomatoes.com/api/public/v1.0/movies.json');
I'm trying to create a more than average complex form with custom actions on some controls. The main controller of the view is holding the model that will be saved at the end. Inside this main controller, I have a separate controller for each input control that has some specific actions.
Here is a short example and the question is, if I want to implement the UserChoiceCtrl.selectLastUser function, how can I do without using $scope ?
More generally, how can I access to a model in the main controller in a child controller ? It's easy in the view, but how can I do in the controller code ?
#Plunker if you prefer
angular.module('myApp', []);
angular.module('myApp')
.controller('TaskCtrl', [
function() {
var viewModel = this;
// This is injected in controller in real life
viewModel.users = [
{login: 'Tom', password: '123'},
{login: 'Stanley', password: '123'},
{login: 'Joe', password: '123'},
{login: 'Katy', password: '123'},
{login: 'Kate', password: '123'},
{login: 'Tony', password: '123'}
];
viewModel.task = {
user: viewModel.users[0],
description: ''
};
viewModel.save = function() {
alert(angular.toJson(viewModel.task));
};
}
]);
angular.module('myApp')
.controller('UserChoiceCtrl', [
function() {
var viewModel = this;
viewModel.selectLastUser = function() {
// No way to access the task variable # TaskCtrl ?
// The following line is working but using $scope
// $scope.taskCtrl.task.user = $scope.taskCtrl.users[5];
};
}
]);
body {
font-family: 'Arial';
}
label,
input,
textarea {
display: block;
}
label {
margin-top: 8px;
}
<!DOCTYPE html>
<html data-ng-app="myApp">
<head>
<script data-require="angular.js#1.4.0" data-semver="1.4.0" src="https://code.angularjs.org/1.4.0/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body data-ng-controller="TaskCtrl as taskCtrl">
<h1>New task</h1>
<form name="taskCtrl.taskForm">
<label>Description</label>
<textarea data-ng-model="taskCtrl.task.description"></textarea>
<div data-ng-controller="UserChoiceCtrl as userChoiceCtrl">
<label>User</label>
<select data-ng-model="taskCtrl.task.user" data-ng-options="user as user.login for user in taskCtrl.users"></select>
<button data-ng-click="userChoiceCtrl.selectLastUser()">Last user of list</button>
</div>
<br>
<button data-ng-click="taskCtrl.save()">Save</button>
</form>
</body>
</html>
Try this
<button data-ng-click="userChoiceCtrl.selectLastUser(taskCtrl.task.user)">Last user of list</button>
viewModel.selectLastUser = function(user) {
alert(user);
// No way to access the task variable # TaskCtrl ?
// The following line is working but using $scope
// $scope.taskCtrl.task.user = $scope.taskCtrl.users[5];
};
A way could be creating the main controller as a service and injecting it to the children:
http://fdietz.github.io/recipes-with-angular-js/controllers/sharing-code-between-controllers-using-services.html
See if this serves the purpose,
basically i am getting an instance of the task controller using the $controller service.
angular.module('myApp')
.controller('UserChoiceCtrl', function ($controller) {
var task = $controller('TaskCtrl');
console.log("Task", task);
var viewModel = this;
viewModel.selectLastUser = function () {
// No way to access the task variable # TaskCtrl ?
// The following line is working but using $scope
// $scope.taskCtrl.task.user = $scope.taskCtrl.users[5];
task.task.user = task.users[5];
alert ( task.task.user.login);
};
console.log("User", viewModel)
});