While running the following code the error "Error: [$injector:unpr] Unknown provider: ItemsProvider <- Items" occurs.
HTML code:
<div ng-controller="ShoppingController">
<table>
<tr>
<td>{{items.title}}</td>
<td>{{items.price}}</td>
</tr>
</table>
Javascript code :
var angModule = angular.module('ShoppingModule',[]);
angModule.factory('Items', function() {
var items = {};
items.query = function() {
return [{title :'JW',price:100}];
}
return items;
}) ;
function ShoppingController($scope, Items) {
$scope.items = Items.query();
}
How to fix this
Your factory method needs to return the object that will be injected. With the code above, it isn't returning anything. Should be:
var angModule = angular.module('ShoppingModule',[]);
angModule.factory('Items', function() {
var items = {};
items.query = function() {
return [{title :'JW',price:100}];
}
return items;// <----- Add this
});
function ShoppingController($scope, Items) {
$scope.items = Items.query();
}
Related
This is regarding Angular JS One, so I created a simple app in my plunkr.
What I did? , I created a factory called app.js and a myController.js.
The problem is the Get Method from controller.js, i dont know how to write it properly so it will pass the list of data to the html. Please check on methods getData(app.js)and Get(controller.js). What are the mistakes?
Note : Add and Edit are working fine using these three layers (app->controller->view) that i need.
PS: I tried nothing yet.
Thanks!!!
John
Below is my app.js or business
angular.module('myFirstApp',['ngRoute'])
.config(function($routeProvider){
$routeProvider
.when('/home',{templateUrl : 'home.html'})
.when('/people',{templateUrl : 'people.html'})
.when('/about',{templateUrl : 'about.html'})
.when('/contact',{templateUrl : 'contact.html'})
})
.factory('personFactory',function(){
function getData(){
$http.get('iphone.json').success(function(result){
return result;
}).error(function(error){
alert(error.error + "/" + error.statusCode);
});
}
function insertData(Name,Email,Password,Mobile){
//update data to database
var x = "Record added successfuly.";
return x;
}
function updateData(){
//update data to database
var x = "Record updated successfuly.";
return x;
}
return {
getData : getData,
insertData,
updateData
};
})
Below is my controller.js
angular.module('myFirstApp')
.controller('myController',function($scope,$http,personFactory){
$scope.Add = function(){
var x = personFactory.insertData($scope.Name,$scope.Email,$scope.Password,$scope.Mobile,$scope.result);
$scope.Message = x;
return $scope.Message;
}
$scope.Edit = function(){
var x = personFactory.updateData();
$scope.Message = x;
return $scope.Message;
}
$scope.Get = function(){
var x = personFactory.getData();
$scope.PeopleList = x;
return $scope.PeopleList;
}
})
Below is my view
<html>
<head>
<title></title>
<script src="app.js"></script>
</head>
<body>
<p>People</p>
<table ng-controller='myController'>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Model</th>
<th>Status</th>
<th>Purchased on</th>
</tr>
</thead>
<tr ng-repeat="values in PeopleList">
<td>{{values.name}}</td>
<td>{{values.email}}</td>
<td>{{values.model}}</td>
<td>{{values.status}}</td>
<td>{{values.purchasedate}}</td>
</tr>
</table>
</body>
</html>
The factory needs to return a JS Object that encapsulate all the functionalities, like this
// Data factory
app.factory("Data", function () {
return {
add: function () {
// add logic here
},
get: function () {
// get logic here
}
}
}
I guess you're having a little problem on the $http.get('iphone.json') within the factory. Maybe you should try to use a callback to handle that, like this:
app.js:
function getData(callback) {
$http.get('iphone.json').success(function(result){
callback(result);
}).error(function(error){
alert(error.error + "/" + error.statusCode);
});
}
controller.js:
$scope.Get = function(){
personFactory.getData(function(result) {
$scope.PeopleList = result;
});
}
Maybe this question was asked before, but i tried the solutions i saw in other posts such as disabling the fast watch, but nothing seems to work...
I have a grid using Angular ui-grid in my web page and the behavior i'm seeking for is that after click on a button the data must be updated. The issue is i can see that gridOptions.data is updated, the columnDefs too, even the length but view doesn't update, also the displaying becomes a bit messy and i have to scroll to get it right.
Here's my code
Controller :
(function(app) {
'use strict';
app.controller('Ctrl', Ctrl);
function Ctrl($scope, $routeSegment, $log, $filter) {
$log.debug('Controller - init()');
// Set ViewModel Object - will be exported in View
var viewModel = this;
viewModel.gridOptionsData = [];
viewModel.gridOptions = {};
viewModel.gridOptions.paginationPageSizes = [25, 50, 75];
viewModel.gridOptions.paginationPageSize = 25;
viewModel.gridOptions.data = [];
viewModel.gridOptions.rowIdentity = function(row) {
return row.id;
};
viewModel.gridOptions.getRowIdentity = function(row) {
return row.id;
};
$scope.showgrid = false;
$scope.filterText;
viewModel.refreshData = function() {
viewModel.gridOptions.data = $filter('filter')(viewModel.gridOptionsData, $scope.filterText, undefined);
};
$scope.$watch('dataStructure', function(data) {
if (angular.isDefined(data) && !angular.equals(data, [])) {
var struct = [];
for (var key in data[0]) {
if (angular.equals(key, 'id')) {
struct.push({
field: key,
visible : false
});
} else {
struct.push({
field: key,
});
}
}
viewModel.gridOptionsData = data;
viewModel.gridOptions.data = data;
viewModel.gridOptions.columnDefs = struct;
$scope.showgrid = true;
}
});
}
}(angular.module('app')));
View :
<div class="gridStyle" ui-grid="pageViewModel.gridOptions" ui-grid-pagination ></div>
<input type="text" ng-model="$parent.filterText" ng-change="pageViewModel.refreshData()" placeholder="Search / Filter" />
Appreciate your help
I'm tryin to make this example to use xml as json data. But i ve some problem about these code.
courses = x2js.xml_str2json(data);
console.log(courses.books.course);
$scope.todos =courses.books.course;
In the xml of example. There are books and course tag. But i didnt understand where is 'courses' come from.
I'm tryin to do same example with this xml example
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<DocumentElement xmlns="">
<semt_kodlari diffgr:id="semt_kodlari1" msdata:rowOrder="0">
<semt_adi>ALTIKAT</semt_adi>
</semt_kodlari>
</DocumentElement>
</diffgr:diffgram>
And here is my HTML part:
X = x2js.xml_str2json(data);
console.log(X.DocumentElement.semt_kodlari);
$scope.todos = X.DocumentElement.semt_kodlari;
When i run this code i take the "Cannot read property 'semt_kodlari' of undefined" error. So can somebody tell me what is wrong in my code and What is the diffrence about course and course's' ?
I think you are only missing one parent of your object. If you add diffgram to you console.log it should work as expected.
See the demo below or here at jsfiddle.
var todoApp = angular.module('todosApp', []);
todoApp.factory('todoFactory', function ($http) {
var factory = {};
factory.getTodos = function () {
return $http.get("http://cdn.rawgit.com/motyar/bcf1d2b36e8777fd77d6/raw/bfa8bc0d2d7990fdb910927815a40b572c0c1078/out.xml");
}
return factory;
});
todoApp.factory('getXMLDataFactory', function() {
var x2js = new X2JS(),
//xml ="<MyRoot><test>Success</test><test2><item>val1</item><item>val2</item></test2></MyRoot>";
xml = '<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">'+
'<DocumentElement xmlns="">'+
'<semt_kodlari diffgr:id="semt_kodlari1" msdata:rowOrder="0">'+
'<semt_adi>ALTIKAT</semt_adi>'+
'</semt_kodlari>'+
'</DocumentElement>'+
'</diffgr:diffgram>';
console.log(xml, x2js);
return {
get: function() {
return x2js.xml_str2json(xml);
}
};
});
todoApp.controller('todosCtrl', function ($scope, todoFactory, getXMLDataFactory) {
$scope.todos = [];
//loadTodos();
loadData();
function loadTodos() {
todoFactory.getTodos().success(function (data) {
console.log(data);
courses = x2js.xml_str2json(data);
console.log(courses.books.course);
$scope.todos = courses.books.course;
});
}
function loadData() {
console.log('test');
$scope.todos = getXMLDataFactory.get()
.diffgram.DocumentElement.semt_kodlari;
console.log($scope.todos);
}
});
<script src="http://demos.amitavroy.com/learningci/assets/js/xml2json.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="todosApp" ng-controller="todosCtrl">
<h2>Parsing XML data with AngularJS</h2>
{{todos|json}}
</div>
I am connecting to the Yahoo weather service API and made a little simple weather app using Angular. I also created a F - C temperature converter that triggers with the help of ng-change(). However for some reason this only works once on initialization.
For some reason I can not make sense why ng-repeat would only fire once inside an ng-repeat. Please see code below. Any help would be appreciated.
***I should mentioned that when I placed a "debugger" inside my function called, changedTemperatureTo, it triggers the "debugger" when I convert from F->C, but the "debugger" doesn't even trigger from C->F, the second time round. By second time around, I mean after I flipped the radio button from F->C the first time. When I flip it back, nothing happens - Debugger doesn't trigger.
VIEW:
{{date}}
<span ng-repeat="temp in temperatureNames">
<input type="radio" name="selectedTemperatureNamed" ng-model="selectedTemperatureName" ng-value="temp" ng-change="changedTemperatureTo(temp)"/> {{temp}}
</span>
<select ng-model="sort">
<option value="cityNameForForecast(td)">City</option>
<option value="high">High</option>
<option value="low">Low</option>
</select>
<input type="checkbox" ng-model="reverse"/> <small>*Check to Reverse Order</small>
<div ><br>
<table class="tg">
<thead>
<tr >
<th class="tg-031e"></th>
<th class="tg-031e"></th>
<th class="tg-031e"></th>
<th class="tg-031e">High</th>
<th class="tg-031e">Low</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="td in forecastAll | orderBy:sort:reverse">
<th class="tg-031e">{{cityNameForForecast(td)}}</th>
<th class="tg-031e"><img src="http://l.yimg.com/a/i/us/we/52/{{ td.code }}.gif"></th>
<th class="tg-031e">{{td.text}}</th>
<th class="tg-031e">{{td.high}}</th>
<th class="tg-031e">{{td.low}}</th>
</tr>
</tbody>
</table>
</div>
CONTROLLER:
/*global angular */
var weatherControllers = (function () {
var weatherControllers = angular.module('weatherControllers', []);
// Declare the application controller and inject the scope reference.
weatherControllers.controller('AppCtrl', ['$scope', function ($scope) {
// Define the title model.
$scope.title = "AngularJS Tutorial - Yahoo Weather App";
}]);
// Inject the scope and new weatherService reference into the controller.
weatherControllers.controller('ListCtrl', ['$scope', 'weatherService', function ($scope, weatherService) {
// Define the forecast data.
}]);
// Inject the scope and new weatherService reference into the controller.
weatherControllers.controller('WeatherCtrl', ['$scope', 'weatherService',
function ($scope, weatherService) {
// Define the forecast data.
// forcastOne >
weatherService.getWeather('Vancouver').success(function (data) {
$scope.forecastVan = weatherService.getForecastFromData(data);
console.log("forecastVan");
console.log($scope.forecastVan);
// console.log($scope.forecastVan[0]);
// console.log("$scope.forecastVan[0]['date']");
// console.log($scope.forecastVan[0]['date']);
$scope.forecastDate = $scope.forecastVan[0]['date'];
weatherService.getWeather('Honolulu').success(function (data) {
$scope.forecastHon = weatherService.getForecastFromData(data);
console.log("forecastHon");
console.log($scope.forecastHon);
console.log($scope.forecastHon[0]);
weatherService.getWeather('San Diego').success(function (data) {
$scope.forecastSan = weatherService.getForecastFromData(data);
console.log("forecastSan");
console.log($scope.forecastSan);
console.log($scope.forecastSan[0]);
weatherService.getWeather('Havana Cuba').success(function (data) {
$scope.forecastHav = weatherService.getForecastFromData(data);
console.log("forecastHav");
console.log($scope.forecastHav);
console.log($scope.forecastHav[0]);
// Create index model
$scope.forecastAll = [$scope.forecastVan[0], $scope.forecastHon[0], $scope.forecastSan[0], $scope.forecastHav[0]]
});
});
});
});
$scope.cityNameForForecast = function (forecast) {
if ($scope.forecastVan[0] == forecast) {
return 'Vancouver';
}
else if ($scope.forecastHon[0] == forecast) {
return 'Honolulu';
}
else if ($scope.forecastSan[0] == forecast) {
return 'San Diego';
}
else if ($scope.forecastHav[0] == forecast) {
return 'Havana Cuba';
}
};
// Temperature
$scope.temperatureNames = ['C', 'F'];
$scope.selectedTemperatureName = $scope.temperatureNames[1];
$scope.changedTemperatureTo = function (temperatureName) {
// debugger;
if (temperatureName == 'C') {
$scope.forecastAll = weatherService.arrayToCelsius($scope.forecastAll);
}
else if (temperatureName == 'F') {
$scope.forecastAll;
}
};
}]);
// Inject scope, $routeParams, and cardService
weatherControllers.controller('DetailCtrl', ['$scope', '$routeParams', 'weatherService',
function ($scope, $routeParams, weatherService) {
weatherService.getWeather($scope, $routeParams.cityID);
$scope.cityName = $routeParams.cityName;
weatherService.getWeather($routeParams.cityName).success(function (data) {
$scope.forecast = weatherService.getForecastFromData(data);
});
$scope.temperatureNames = ['C', 'F'];
$scope.selectedTemperatureName = $scope.temperatureNames[1];
}]);
return weatherControllers;
}());
SERVICES:
weatherApp.factory("weatherService", function ($http) {
'use strict';
return {
doSomething: function ($scope) {
},
getWeather: function (city) {
var url = this.getUrlForCity(city);
return $http.get(url);
},
getUrlForCity: function (city) {
// Weather codes:
var weatherCodes = {'Vancouver': 'CAXX0518', 'Honolulu': 'USHI0026', 'San Diego': 'USCA0982', 'Havana Cuba': 'CUXX0003'}
var city = weatherCodes[city] // Now on can call all cities at once
var yahooAPI = "'http://weather.yahooapis.com/forecastrss?p=";
var format = "'&format=json&diagnostics=true&callback=";
var yql = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20rss%20where%20url%3D";
var url = yql + yahooAPI+ city + format;
return url;
},
getForecastFromData: function (data) {
try {
var stringified = JSON.stringify(data); // Convert to a string.
stringified = stringified.split("\\n").join(""); // Remove new line '/n'.
var listing = JSON.parse(stringified); // Convert to object.
var forecast = []; // Store 5 day forecast.
var forecastDate = []; // Stores forecast date
for (var result in listing) {
for (var item in listing[result].results) {
for (var day in listing[result].results.item.forecast) {
forecast.push(listing[result].results.item.forecast[day]);
}
}
}
}
catch (error) {
alert("Weather reading error:" + error.name + ": "
+ error.message);
}
return forecast;
},
arrayToCelsius: function (forecastArray) {
for (var i = 0; i < forecastArray.length; i++) {
forecastArray[i]['high'] = this.getCelsius(forecastArray[i]['high']);
forecastArray[i]['low'] = this.getCelsius(forecastArray[i]['low']);
}
return forecastArray;
},
getCelsius: function (fahrenheit) {
var fTempVal = this.getForecastFromData(fahrenheit);
// debugger;
// $scope.celsius = this.getForecastFromData;
var celsius = ((fahrenheit - 32) * 0.56).toFixed(0);
return celsius; // Calculation goes here.
}
}
});
From what I can see, you initially set the temperature to be in Fahrenheit.
// Temperature
$scope.temperatureNames = ['C', 'F'];
$scope.selectedTemperatureName = $scope.temperatureNames[1];
The issue happens here:
$scope.changedTemperatureTo = function(temperatureName) {
// debugger;
if (temperatureName == 'C') {
$scope.forecastAll = weatherService.arrayToCelsius($scope.forecastAll);
} else if (temperatureName == 'F') {
/*
You aren't doing anything to the forcastAll variable when the temperature
is F
*/
$scope.forecastAll;
}
};
Nothing is happening when the temperatureName == 'F'. So it'll convert from Farenheight to Celcius, but then nothing happens when going back.
Hope this helps!
I am having a problem with the dynamic creation of a Form. I have a directive that gets set against a form element. It uses Jquery to get the element by id. However it seems that it has not yet been added to the DOM.
<form class="form-horizontal">
<div class="control-group" ng-repeat="field in viewModel.fields">
<label class="control-label">{{field.label}}</label>
<div class="controls" ng-switch="field.type">
<input ng-switch-when="text" type="text" id="{{field.label}}" ng-model="field.data" validator="viewModel.validator" ruleSetName="personFirstNameRules"/>
<span ng-switch-when="text" validation-Message-For="{{field.label}}"></span>
</div>
</div>
<button ng-click="testID()">Submit</button>
</form>
If I hard code the ID attribute for the text field and on the span element validation-Message-For then their is no issue.The area where i am getting undefined is
var errorElementController = angular.element(errorElement).controller('ngModel');
var validatorsController = angular.element(errorElement).controller('validator');
The full directive is here
(function (angular, $) {
angular.module('directivesModule')
.directive('validationMessageFor', [function () {
return {
link: function (scope, element, attributes) {
var errorElementId = attributes.validationMessageFor;
if (!errorElementId) {
return;
}
var areCustomErrorsWatched = false;
var watchRuleChange = function (validationInfo, rule) {
scope.$watch(function () {
return validationInfo.validator.ruleSetHasErrors(validationInfo.ruleSetName, rule.errorCode);
}, showErrorInfoIfNeeded);
};
var watchCustomErrors = function (validationInfo) {
if (!areCustomErrorsWatched && validationInfo && validationInfo.validator) {
areCustomErrorsWatched = true;
var validator = validationInfo.validator;
var rules = validator.validationRules[validationInfo.ruleSetName];
for (var i = 0; i < rules.length; i++) {
watchRuleChange(validationInfo, rules[i]);
}
}
};
//alert(errorElementId);
// get element for which we are showing error information by id
var errorElement = $("#" + errorElementId);
console.log(angular.element(errorElement));
var errorElementController = angular.element(errorElement).controller('ngModel');
var validatorsController = angular.element(errorElement).controller('validator');
console.log(errorElementController);
console.log(validatorsController);
var getValidationInfo = function () {
return validatorsController && validatorsController.validationInfoIsDefined() ? validatorsController.validationInfo : null;
};
var validationChanged = false;
var subscribeToValidationChanged = function () {
if (validatorsController.validationInfoIsDefined()) {
validatorsController.validationInfo.validator.watchValidationChanged(function () {
validationChanged = true;
showErrorInfoIfNeeded();
});
// setup a watch on rule errors if it's not already set
watchCustomErrors(validatorsController.validationInfo);
}
};
var getErrorMessage = function (value) {
var validationInfo = getValidationInfo();
if (!validationInfo) {
return '';
}
var errorMessage = "";
var errors = validationInfo.validator.errors[validationInfo.ruleSetName];
var rules = validationInfo.validator.validationRules[validationInfo.ruleSetName];
for (var errorCode in errors) {
if (errors[errorCode]) {
var errorCodeRule = _.findWhere(rules, { errorCode: errorCode });
if (errorCodeRule) {
errorMessage += errorCodeRule.validate(value).errorMessage;
break;
}
}
}
return errorMessage;
};
var showErrorInfoIfNeeded = function () {
var validationInfo = getValidationInfo();
if (!validationInfo) {
return;
}
var needsAttention = validatorsController.ruleSetHasErrors() && (errorElementController && errorElementController.$dirty || validationChanged);
if (needsAttention) {
// compose and show error message
var errorMessage = getErrorMessage(element.val());
// set and show error message
element.text(errorMessage);
element.show();
} else {
element.hide();
}
};
subscribeToValidationChanged();
if (errorElementController)
{
scope.$watch(function () { return errorElementController.$dirty; }, showErrorInfoIfNeeded);
}
scope.$watch(function () { return validatorsController.validationInfoIsDefined(); }, subscribeToValidationChanged());
}
};
}]);})
(angular, $);
The error on the console is
TypeError: Cannot read property 'validationInfoIsDefined' of undefined
at subscribeToValidationChanged (http://localhost/trax/app/Directives/validationMessage.js:50:52)
at link (http://localhost/trax/app/Directives/validationMessage.js:103:24)
at nodeLinkFn (https://code.angularjs.org/1.2.13/angular.js:6271:13)
at compositeLinkFn (https://code.angularjs.org/1.2.13/angular.js:5682:15)
at publicLinkFn (https://code.angularjs.org/1.2.13/angular.js:5587:30)
at boundTranscludeFn (https://code.angularjs.org/1.2.13/angular.js:5701:21)
at Object.controllersBoundTransclude [as transclude] (https://code.angularjs.org/1.2.13/angular.js:6292:18)
at https://code.angularjs.org/1.2.13/angular.js:20073:32
at Array.forEach (native)
at forEach (https://code.angularjs.org/1.2.13/angular.js:304:11) <span ng-switch-when="text" validation-message-for="{{field.label}}" class="ng-scope">
you are writing Directive name as camel case when you are define. in this case angular read this directive as - based values
so validation-Message-For should be validation-message-for in your Html code
<span ng-switch-when="text" validation-message-for="{{field.label}}"></span>
and change the input id attribute value assigning type:
remove the {{}} from id attribute
<input ng-switch-when="text" type="text" id="field.label" ng-model="field.data" validator="viewModel.validator" ruleSetName="personFirstNameRules"/>
update
problem with ng-switch when. in your Plunker the input tags are not rendering as input field.
Be aware that the attribute values to match against cannot be expressions.
They are interpreted as literal string values to match against. For example,
ng-switch-when="someVal" will match against the string "someVal" not against the
value of the expression $scope.someVal.
refer this Question. StackOverflow Question
Updated Plunker