I'm trying to create a directive on a controller. The directive will create a table of items returned from djangorestframework.
controller.js:
var expensesApp = angular.module('expensesApp', []);
expensesApp.controller('ShoppingListController', ['$scope', '$http',
function($scope, $http){
$http(
{
method: 'GET',
url: '/items/?format=json'
})
.success(function(data, status, headers, config) {
$scope.items = data;
})
.error(function(data, status, headers, config) {
});
}]);
directive.js
angular.module('expensesApp', [])
.directive('shoppingList', function () {
return {
restrict: 'A',
templateUrl: 'http://localhost:8000/static/angular/partials/shopping-list.html',
controller: 'ShoppingListController'
};
})
The partial being pulled in by the directive:
shopping-list.html
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>ID</th>
<th>NAME</th>
<th>SHOP</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items">
<td>[[ item.id ]]</td>
<td>[[ item.name ]]</td>
<td>[[ item.shop ]]</td>
</tr>
</tbody>
</table>
and the main html page where I define the app and the controller.
items.html
...
<div class="container" ng-app="expensesApp">
<div class="row">
<div class="col-md-6" ng-controller="ShoppingListController">
<div shopping-list></div>
</div>
</div>
</div>
...
The headers of the table in the partial are being pulled into the page, but it's not executing the $http and fetching the items that should make up the content of the table. I get ShoppingListController not a function, got undefined
Everything works if I don't split the table out into a directive. All items are returned and I don't see the error in the console.
Anyone have any idea what I'm doing wrong?
You are redefining module when you create a directive. It should be:
angular.module('expensesApp')
.directive('shoppingList', function () {
return {
restrict: 'A',
templateUrl: 'http://localhost:8000/static/angular/partials/shopping-list.html',
controller: 'ShoppingListController'
};
});
If you pass an array as the second argument to module method angular.module('expensesApp', []), Angular creates a new module without ShoppingListController controller in it. You should use getter syntax angular.module('expensesApp') to retrieve previously created module.
Related
I need to create a new page in one of our legacy app that uses AngularJS1. As I am not an Angular developer so my knowledge in this technology is almost non-existent. I am actually trying to get my hands dirty in this app as we need to maintain it in future. Here is the HTML:
<table id="example" class="table table-striped table-bordered" style="width:100%">
<thead class="text-left">
<tr>
<th>Select</th>
<th>Client Admin</th>
<th>Email</th>
<th>Company</th>
<th>Location</th>
<th>Users</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" /></td>
<td>Bob Jones</td>
<td>BobJones#gmail.com</td>
<td>Tractor-Tract</td>
<td>10</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>Greenview_Hc</td>
<td>Hoffmale</td>
<td>Status</td>
<td>Electronic[Parts]</td>
<td>Pap</td>
</tr>
</tbody>
</table>
Controller:
Console.log('Hello');
app.controller('testController', ['$http', 'APIService', '$scope', '$sessionStorage', '$rootScope', 'StatsService', '$state', '$sce', '$translate',
function ($http, APIService, $scope, $sessionStorage, $rootScope, StatsService, $state, $sce, $translate) {
var myCtrl = this;
myCtrl.title = "Hello World";
debugger;
}]);
Directive:
app.directive('testingApp', function () {
return {
scope: {
initialData: '=info',
},
templateUrl: 'test/test.html',
controller: 'testController',
controllerAs: 'tc'
};
});
The issue is I can not get the controller to get hit. Even the console is not showing anything. What is wrong with this code? This is my very first try at Angular and I am using existing code to create my testing page.
EDIT:
I went through the app and tried to understand its architecture. Here is what I found:
All the controllers are defined in app-controller.js with code. Yes, this file has complete controller code and there are individual controllers as well with the same code. For example if there is a controller "MyController.js" it has its own code and the same code is written in app-controller.js as well
All the directives are defined in app-directives.js
There is a config file with code like:
$stateProvider.state('index.testing', {
url: "/testing",
templateUrl: "testing/testing.html",
controller: "testingController",
controllerAs: "testing",
data: {
requireLogin: true,
accessPage: 'Test.aspx',
pageTitle: "Testing View"
}
index.html includes only config.js
For the "controller to be hit", the directive needs to be included in the HTML:
<body ng-app="app">
<testing-app info="'world'">
</testing-app>
</body>
The DEMO
app = angular.module("app",[]);
app.directive('testingApp', function () {
return {
scope: {
initialData: '<info',
},
template: `<fieldset>
title={{tc.title}}
</fieldset>`,
controller: 'testController',
controllerAs: 'tc',
bindToController: true
};
});
app.controller('testController',
function () {
var myCtrl = this;
myCtrl.$onInit = function() {
myCtrl.title = "Hello "+myCtrl.initialData;
console.log("Hello", myCtrl.title);
debugger;
};
});
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
<h1>Testing App</h1>
<testing-app info="'world'">
</testing-app>
</body>
First of all, please don't call AngularJS legacy. AngularJS is still widely used and supported, and a majority in the so called angular world. Have a look at this Google trends comparison.
Secondly, to now actually address your question hehe.
I assume that the first HTML snippet is the test.html file contents.
I would recommend re-writing that in the more angular way, using ng-repeat for the <tr>s
<table id="example" class="table table-striped table-bordered" style="width:100%">
<thead class="text-left">
<tr>
<th>Select</th>
<th>Client Admin</th>
<th>Email</th>
<th>Company</th>
<th>Location</th>
<th>Users</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="dataEntry in testController.initialData">
<td><input type="checkbox" ng-model="dataEntry.select"/></td>
<td>{{dataEntry.clientAdmin}}</td>
<td>{{dataEntry.email}}</td>
<td>{{dataEntry.company}}</td>
<td>{{dataEntry.location}}</td>
<td>{{dataEntry.users}}</td>
</tr>
</tbody>
</table>
In order for your <table> HTML code to render somewhere, you need to instantiate your directive there, as such:
<!-- Page HTML -->
<!-- someObjectWithInfo would come the controller of this page -->
<testing-app info="someObjectWithInfo"></testing-app>
<!-- Page HTML -->
P.S. Your Console.log('Hello'); should be inside your controller function, not outside, as such:
app.controller('testController', ['$http', 'APIService', '$scope', '$sessionStorage', '$rootScope', 'StatsService', '$state', '$sce', '$translate',
function ($http, APIService, $scope, $sessionStorage, $rootScope, StatsService, $state, $sce, $translate) {
var myCtrl = this;
myCtrl.title = "Hello World";
console.log("Hello", myCtrl.title);
debugger;
}]);
Hope this helps :)
I want to show the object in view. The object itself is the controller, but the html does not have access to its properties (probably not see the model)! Maybe the problem ui routing?
app.js
(function () {
'use strict';
angular
.module('hawk', [
'ngWebsocket',
'ui.bootstrap',
'ui.router',
'hawk.controllers',
'hawk.services',
'hawk.directives'
])
.config(['$stateProvider', '$urlRouterProvider', router])
.run(['$rootScope', main]);
angular.module('hawk.services', []);
angular.module('hawk.directives', []);
angular.module('hawk.controllers', []);
function router($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/list');
// CARDS OBJECT VIEW
$stateProvider
.state('list', {
abstract: true,
url: '/list',
templateUrl: '/app/app-eng/controllers/list.html',
controller: 'ListController as dc'
})
.state('list.cards-list', {
url: '/cards-list',
templateUrl: '/app/app-eng/controllers/object-card/cards-list.html',
controller: 'CardsListController as dc',
})
.state('list.contract', {
url: '/contract',
templateUrl: '/app/app-eng/controllers/object-card/contract.html',
controller: 'ContractController as dc',
})
}
function main ($rootScope) {
$rootScope.object = {};
}
})();
The submittion list.cards-list I have access to the object (from model), but submitting list.contract I get the object and can not access its properties (in model). Why?
list.html
<div class="list-group col-md-2 sidebar-offcanvas">
<uib-tabset active="activePill" vertical="true" type="pills">
<uib-tab index="0" heading="Cards list" ui-sref="list.cards-list"></uib-tab>
<uib-tab index="1" heading="Contract" ui-sref="list.contract"></uib-tab>
</uib-tabset>
</div>
<div class="col-md-10">
<div ui-view></div>
</div>
contract.html
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Contract #{{ 2222222}}</h3>
</div>
<table class="table table-condensed">
<tr>
<td width="10%" align="right"><strong>№ contract:</strong></td>
<td>{{dc.data.id}}</td>
</tr>
<tr>
<td align="right"><strong>Date start:</strong></td>
<td>{{dc.data.cdstart}}</td>
</tr>
<tr>
<td align="right"><strong>Date end:</strong></td>
<td>{{dc.data.cdend}}</td>
</tr>
<tr>
<td align="right"><strong>Type name:</strong></td>
<td>{{dc.data.tyonames}}</td>
</tr>
<tr>
<td align="right"><strong>Category.:</strong></td>
<td>{{dc.data.ccategory}}</td>
</tr>
<tr>
<td align="right"><strong>Police department:</strong></td>
<td>{{dc.data.rpnames}}</td>
</tr>
</table>
</div>
contract.js
(function() {
'use strict';
angular
.module('hawk.controllers')
.controller('ContractController', ContractController);
ContractController.$inject = ['$scope', 'Websocket'];
function ContractController ($scope, Websocket) {
var vm = this;
vm.data = {};
init();
function getContracts (id) {
console.log('getContracts-id', id);
Websocket.getContracts({ id: id }).then(function(data) {
console.log('getContracts-data', data);
vm.data = data.data;
console.log('getContracts-vm.data', vm.data);
});
}
function getAddress (id) {
Websocket.getAddress({ id: id }).then(function(data) {
console.log('getAddress', data);
vm.address = data.data;
});
}
function init () {
$scope.$watch('object.id', function(newValue, oldValue) {
console.log('cc', newValue, oldValue, $scope.object.id);
getContracts($scope.object.id);
});
}
}
})();
you have to access your variables with the "vm." inside your html -> "{{vm.data}}" etc.
//EDIT:
If you want to access them without the "vm" you have to put your variables into the "$scope" in your controller.
I am trying pass id in the url so that it can be use by other page more specifically the detail page but i keep getting nothing. the url is going to the correct route but the id is not getting passed in. i have no idea what i'm doing wrong.
here my app.js file:
$stateProvider.state('contact', {
url: '/contact',
templateUrl: 'templates/contact.html',
controller: 'mainController'
});
$stateProvider.state('contact.detail', {
url: '/detail/:id',
templateUrl: 'templates/contact.detail.html',
controller: 'detailController'
});
and here is my controller file:
myApp.controller('detailController', ['$scope', '$stateParams',
function ($scope, $stateParams) {
'use strict';
$scope.peoples = $scope.peoples[$stateParams.id];
}]);
and here is my contact file:
<div class="container">
<div class="row">
<div class="col-md-6">
<table class="table table-striped">
<thead>
<th>First name</th>
<th>Last name</th>
<th>Age</th>
</thead>
<tbody>
<tr ng-repeat="person in peoples">
<td><a ui-sref="contact.detail({id: person.id})">{{person.firstname}}</a></td>
<td>{{person.lastname}}</td>
<td>{{person.age}}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-6">
<div ui-view></div>
</div>
</div>
There is a working example
One thing is:
searching with indexer, e.g. $scope.peoples[someIdValue] will not find by ID but by position (index)
The second point would be:
do not re-assign a reference $scope.peoples with new value (and lose that reference)
So, this should be the fix (using lodash to find person)
.controller('detailController', ['$scope', '$stateParams',
function($scope, $stateParams) {
//$scope.peoples = $scope.peoples[$stateParams.id];
$scope.person = _.find($scope.peoples, {id: $stateParams.id});
}])
Check that all in action here
I just started learning Angular and I am having trouble retrieving data based on a http-get request. It works when I simply retrieve all movies, but not when I try to retrieve movies based on a search term (cfr. search.html). I hope someone can tell me where I went wrong, I really can't see it. Thank you in advance.
app.js:
var app;
(function() {
app = angular.module('imdb', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/search', {
controller: 'SearchController',
templateUrl: 'views/search.html'
})
.when('/movies', {
controller: 'MovieController',
templateUrl: 'views/movies.html' //works fine
})
.otherwise({
redirectTo: '/movies'
});
});
})();
SearchController.js
(function (app) {
app.controller('SearchController', ['$http', '$scope', function ($http, $scope) {
$scope.movies = [];
$scope.searchMovie = function(title) {
$http.get('https://angularbackend.azurewebsites.net/api/Movies/Search?title=' + title)
.success(function(data) {
$scope.movies = data;
});
};
}]);
})(app);
search.html
<div>
<form class="form" novalidate name="searchMovies" ng-submit="SearchController.searchMovie(title)" >
<input type="text" ng-model="title" class="form-control" placeholder="enter title">
<button type="submit" class="btn btn-primary btn-block">Search</button>
</form>
<table class="table">
<thead>
<tr>
<th>poster</th>
<th>title</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="movie in movies">
<td>{{ movie.title }}</td>
</tr>
</tbody>
</table>
</div>
Replace
SearchController.searchMovie(title)
by
searchMovie(title)
All expressions are always evaluated on the scope. So the first, incorrect one, will try to invoke the method searchMovie of $scope.SearchController, which doesn't exist.
Also note that success() is deprecated for quite some time now. Use then():
$http.get('https://angularbackend.azurewebsites.net/api/Movies/Search?title=' + title)
.then(function(response) {
$scope.movies = response.data;
});
You should also avoid using string concatenation to pass parameters. Those need to be encoded properly. So rather use
$http.get('https://angularbackend.azurewebsites.net/api/Movies/Search', {params: {title: title}})
.then(function(response) {
$scope.movies = response.data;
});
Hello I am trying to get a url from my api using the ngResource and I have a service that returns the resource. However when I call it inside my controller is gives me an error of Cannot read property 'query' of undefined.
Why is this happening?
This is my service :
(function() {
var app = angular.module('test');
app.service('ContactResource', ['$resource', function($resource) {
return $resource('/contacts/:firstname', {firstname: '#firstname'},
{
'update': {method: 'PUT'}
}
);
}]);
}());
This is my controller
(function() {
var app = angular.module('test');
app.controller('contactsCtrl', ['ContactResource', function($scope, Contacts, ContactResource) {
$scope.contacts = ContactResource.query();
}]);
}());
And this is my HTML
<table class="table table-bordered">
<thead>
<th>Firstname <input type="search" class="pull-right"></th>
</thead>
<tbody>
<tr ng-repeat="contact in contacts">
<td>
<a ng-href="/{{ contact.firstname }}">{{ contact.firstname }}</a>
</td>
</tr>
</tbody>
</table>
Here is your problem:
['ContactResource', function($scope, Contacts, ContactResource)
You need to also inject $scope and Contacts into the array, like this:
['$scope', 'Contacts', 'ContactResource', function($scope, Contacts, ContactResource)
Or Angular will think that 'ContactResource' is the same as $scope.