I am returning objects from a Sqlite database that sometimes returns null for some attributes of this object. For example (item.unit) is sometimes null in the database.
I got this code in my html file
<td class="item-row-quote"><span class="quote-price-text" ng-model="row.dollarPerUnitText"
id="dollarPerUnit">{{ '$/' + item.unit }}</span></td>
How can I make sure the browser display nothing for item.unit instead of displaying null.
This is my controller code
angular.module('canex')
.controller("QuoteController", ['$scope', '$routeParams', '$location', 'ProjectService', 'QuoteService', 'UploadService', 'ClientService', 'ItemService', 'ConditionService',
function ($scope, $routeParams, $location, projectService, quoteService, uploadService, clientService, itemService, conditionService) {
$scope.clientId = $routeParams.clientId;
$scope.projectId = $routeParams.projectId;
$scope.quoteId = $routeParams.quoteId;
$scope.IMG_URL = uploadService.getImageUrl();
$scope.quoteDate = new Date().getFullYear().toString().substr(2, 2);
$scope.items = [];
function _fetchQuote() {
quoteService.getQuote($routeParams.quoteId)
.then(function (response) {
$scope.quote = response.data;
}, $scope.httpErrorCallback);
}
function _fetchItems() {
itemService.getQuoteItems($routeParams.quoteId)
.then(function (response) {
$scope.items = response.data;
}, $scope.httpErrorCallback);
}
function _fetchConditions() {
conditionService.getQuoteConditions($routeParams.quoteId)
.then(function (response) {
$scope.conditions = response.data;
}, $scope.httpErrorCallback);
}
function _fetchClient() {
clientService.getClient($routeParams.clientId)
.then(function (response) {
$scope.client = response.data;
}, $scope.httpErrorCallback);
}
function _fetchProject() {
projectService.getProject($routeParams.projectId)
.then(function (response) {
$scope.project = response.data;
}, $scope.httpErrorCallback);
}
$scope.addRow = function () {
$scope.items.data.push({});
};
$scope.addCondition = function () {
if (document.getElementById("condition-page").style.display == "none") {
document.getElementById("condition-page").style.display = '';
}
$scope.conditions.data.push({})
};
$scope.removeRow = function (index) {
var itemId = $scope.items.data[index].id;
itemService.archiveItem(itemId);
$scope.items.data.splice(index, 1);
};
$scope.removeCondition = function (index) {
var conditionId = $scope.conditions.data[index].id;
conditionService.archiveCondition(conditionId);
$scope.conditions.data.splice(index, 1);
};
$scope.subtotal = function () {
var subtotal = 0;
angular.forEach($scope.items.data, function (item) {
subtotal += item.quantity * item.rate;
});
return subtotal;
};
$scope.generateQuote = function (divName) {
$scope.submitItems();
$scope.submitConditions();
if ($scope.conditions.data.length == 0) {
document.getElementById("condition-page").style.display = "none";
}
var printContents = document.getElementById(divName).innerHTML;
var popupWin;
if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
popupWin = window.open('', '_blank', 'width=600,height=800,scrollbars=no,menubar=no,toolbar=no,location=no,status=no,titlebar=no');
popupWin.window.focus();
popupWin.document.write('<!DOCTYPE html><html><head>' +
'<link rel="stylesheet" type="text/css" href="../css/style.css" />' +
'</head><body onload="window.print()"><div class="reward-body">' + printContents + '</div></html>');
popupWin.onabort = function (event) {
popupWin.document.close();
popupWin.close();
}
} else {
popupWin = window.open('', '_blank', 'width=800,height=600');
popupWin.document.open();
popupWin.document.write('<html><head><link rel="stylesheet" type="text/css" href="../css/style.css" /></head><body onload="window.print()">' + printContents + '</html>');
popupWin.document.close();
}
popupWin.document.close();
return true;
};
$scope.submitItems = function () {
angular.forEach($scope.items.data, function (item) {
if (item.quote_id == undefined) {
delete item.$$hashKey;
item.quote_id = $routeParams.quoteId;
itemService.createItem(item);
}
});
};
$scope.submitConditions = function () {
angular.forEach($scope.conditions.data, function (condition) {
if (condition.quote_id == undefined) {
delete condition.$$hashKey;
condition.quote_id = $routeParams.quoteId;
conditionService.createCondition(condition);
}
})
};
_fetchItems();
_fetchConditions();
_fetchQuote();
_fetchClient();
_fetchProject();
}])
.directive('elastic', [
'$timeout',
function ($timeout) {
return {
restrict: 'A',
link: function ($scope, element) {
$scope.initialHeight = $scope.initialHeight || element[0].style.height;
var resize = function () {
element[0].style.height = $scope.initialHeight;
element[0].style.height = "" + (element[0].scrollHeight + 10) + "px";
};
element.on("input change", resize);
$timeout(resize, 0);
}
};
}
]);
You can use ng-show somthing like :
<td class="item-row-quote">
<span ng-show = "item.unit != null" class="quote-price-text" ng-model="row.dollarPerUnitText" id="dollarPerUnit">{{ '$/' + item.unit }}</span></td>
I hope that this is what you mean by nothing it is not clear.
If you have one or two properties that may have null, then you can update them with empty strings in the controller.
DefaultController.$inject = ['$http'];
function DefaultController($http) {
var vm = this;
vm.item;
function getItem() {
var config = {
transformResponse: function(data, headers) {
if (data) {
if (data.unit === null || data.unit === undefined) {
data.unit = '';
}
}
return data;
}
};
$http.get('/api/items', config)
.success(getItemCompleted);
function getItemCompleted(data) {
vm.item = data;
}
}
}
If you are having many properties that may be null and if you have control of the server side code, then see if you can handle there by returning empty arrays or empty list but not null if not then write a custom filter where you can loop through all the properties of an object and assign empty string to any property that is a falsy value
I am new to angular and node.js.
Basically, I have a table of items and in each row, there is a button click.
If I click the button which is edit, the details should appear in its corresponding textbox for editing.
router.route('/contacts/getone/:pk')
.get(function(req, res, next){
pg.connect(connectionString, function(err, client, done) {
//var id = {pk:req.body.pk};
var contacts = [];
console.log("get1");
console.log(req.params.pk);
var query = client.query("select * from contacts where pk=($1)", [req.params.pk]);
query.on('row', function(row) {
contacts.push(row);
});
query.on('end', function() {
done();
return res.json(contacts);
});
});
});
And this is my angular controller code.
$scope.editContact = function(id) {
contact.getone(id)
.success(function(data) {
$scope.contactlist = data;
//console.log("geone");
//document.getElementById("fname").value = $scope.contactlist.firstname;
//console.log("getall");
//console.log($scope.contactlist.firstname);
//console.log(data["firstname"]);
$scope.formData.firstname = $scope.contactlist.firstname;
$scope.formData.lastname = $scope.contactlist.lastname;
$scope.formData.address = $scope.contactlist.address;
$scope.formData.contact = $scope.contactlist.contact;
// $scope.loading = false;
});
};
Can anyone tell me how to access the values in data which is returned by my node.js code? The code I have in my angular returns undefined values like $scope.contactlist.firstname is undefined.
This is the image of when I do console.log(data);
#Rayin Dabre
----This is my the code of my controller.
angular.module('ContactsControl', [])
.controller('contactController', ['$scope', '$http', 'contact', function($scope, $http, contact) {
$scope.formData = {};
contact.get()
.success(function(data) {
console.log("getall");
$scope.contactlist = data;
// $scope.loading = false;
});
$scope.editContact = function(id) {
contact.getone(id)
.success(function(data) {
$scope.contactlist = data;
//console.log("geone");
//document.getElementById("fname").value = $scope.contactlist.firstname;
console.log(data);
//console.log($scope.contactlist.firstname);
//console.log(data["firstname"]);
$scope.formData.firstname = $scope.contactlist.firstname;
$scope.formData.lastname = $scope.contactlist.lastname;
$scope.formData.address = $scope.contactlist.address;
$scope.formData.contact = $scope.contactlist.contact;
// $scope.loading = false;
});
};
You have to define formData as object({}) or else $scope.formData will be undefined and you can not set property of undefined
Data being received from the api is not an object but an array. You need to return the data once you get the row
Server side
router.route('/contacts/getone/:pk')
.get(function(req, res, next) {
pg.connect(connectionString, function(err, client, done) {
var query = client.query("select * from contacts where pk=($1)", [req.params.pk]);
query.on('row', function(row) {
return res.json(row);
});
});
});
Client side
var data = {
$$hashKey: "008",
contact_num: 123,
email: "a#gmail.com",
firstname: "boy",
lastname: "kigwa",
pk: 2
};
$scope.formData = {};
$scope.contactlist = data;
$scope.formData.firstname = $scope.contactlist.firstname;
$scope.formData.lastname = $scope.contactlist.lastname;
$scope.formData.address = $scope.contactlist.address;
$scope.formData.contact = $scope.contactlist.contact;
alert(JSON.stringify($scope.formData));
.factory('MY', function($http){
return {
mustafa: function(){
var factory = {};
var url = '/uzak/remote.php?callback=JSON_CALLBACK';
var yarro = $http.get(url).success(function(response){
return response.data);
});
return yarro;
}
}
})
.controller('nbgCtrl', function() {
$scope.mangas = MY.mustafa();
})
I wanna use json data above like. But it isn't working. Could you guys help me?
You can return the promise, and then resolve it in the controller:
.factory('MY', function($http){
return {
mustafa: function() {
var url = '/uzak/remote.php?callback=JSON_CALLBACK';
return $http.get(url);
}
};
})
Finally, you have to inject the service to the controller.
.controller('nbgCtrl', function($scope, MY) {
MY.mustafa().success(function(response) {
$scope.mangas = response.data;
);
});
Basically I am testing to see how a PROD version of my app is looking; I proceeded to run it through some gulp tasks (minify, strip unused css etc.) and got this error:
Error: [$injector:unpr] Unknown provider: tProvider <- t <- myActiveLinkDirective
Can anyone help with what's going on here?
This is some my angular code:
var rustyApp = angular.module('rustyApp', [
'ngAnimate',
'ngRoute',
'viewController',
'mm.foundation',
'angular-flexslider',
'ui.router']).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.when('/', {
title: 'home',
templateUrl: '/partials/home.html',
controller: 'HomeController'
}).when('/work', {
title: 'my work',
templateUrl: '/partials/work.html',
controller: 'WorkController'
}).when('/contact', {
title: 'contact',
templateUrl: '/partials/contact.html',
controller: 'ContactController'
}).otherwise({redirectTo: '/'});
// configure html5 to get links working
$locationProvider.html5Mode(true);
}]);
rustyApp.controller('BasicSliderCtrl', function($scope) {
$scope.slides = [
'../images/sliderContent/1.jpg',
'../images/sliderContent/2.jpg',
'../images/sliderContent/3.jpg',
'../images/sliderContent/4.jpg'
];
});
rustyApp.run(function() {
FastClick.attach(document.body);
});
rustyApp.run(['$location', '$rootScope', function($location, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
$rootScope.title = current.$$route.title;
});
}]);
rustyApp.controller('HomeController', function($scope) {
$scope.pageClass = 'home';
});
rustyApp.controller('WorkController', function($scope) {
$scope.pageClass = 'work';
});
rustyApp.controller('ContactController', function($scope) {
$scope.pageClass = 'contact';
});
rustyApp.controller('OffCanvasDemoCtrl', function($scope) {});
var OffCanvasDemoCtrl = function($scope) {};
rustyApp.controller('ContactController', function($scope, $http) {
$scope.result = 'hidden'
$scope.resultMessage;
$scope.formData; //formData is an object holding the name, email, subject, and message
$scope.submitButtonDisabled = false;
$scope.submitted = false; //used so that form errors are shown only after the form has been submitted
$scope.submit = function(contactform) {
$scope.submitted = true;
$scope.submitButtonDisabled = true;
if (contactform.$valid) {
$http({
method: 'POST',
url: '../partials/mailer.php',
data: $.param($scope.formData), //param method from jQuery
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
} //set the headers so angular passing info as form data (not request payload)
}).success(function(data) {
console.log(data);
if (data.success) { //success comes from the return json object
$scope.submitButtonDisabled = true;
$scope.resultMessage = data.message;
$scope.result = 'bg-success';
if ($scope.result === 'bg-success') {
$scope.class = "bg-success";
}
// if($scope.result){setTimeout(window.location.reload(true),4000);}
if ($scope.result) {
setTimeout(function() {
window.location.reload(true)
}, 4000);
}
} else {
$scope.submitButtonDisabled = false;
$scope.resultMessage = data.message;
$scope.result = 'bg-danger';
}
});
} else {
$scope.submitButtonDisabled = false;
if ($scope.submitButtonDisabled) {
$scope.class = "bg-danger";
}
$scope.resultMessage = 'Failed Please fill out all the fields.';
$scope.result = 'bg-danger';
}
}
});
var viewController = angular.module('viewController', []);
rustyApp.directive('myActiveLink', function($location) {
return {
restrict: 'A',
scope: {
path: "#myActiveLink"
},
link: function(scope, element, attributes) {
scope.$on('$locationChangeSuccess', function() {
if ($location.path() === scope.path) {
element.addClass('uk-active');
} else {
element.removeClass('uk-active');
}
});
}
};
});
// var $j = jQuery.noConflict();
// $j(function() {
// $j('#Container').mixItUp();
// });
rustyApp.directive('mixItUp', function() {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope, element, attrs) {
var $j = jQuery.noConflict();
var mixContainer = $j('#Container');
mixContainer.mixItUp();
mixContainer.on('$destroy', function() {
mixContainer.mixItUp('destroy');
});
}
});
rustyApp.directive('share', function() {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope, element, attrs) {
var $s = jQuery.noConflict();
// mixContainer.on('$destroy', function() {
// mixContainer.mixItUp('destroy');
// });
var $s = new Share(".share-button", {
networks: {
facebook: {
app_id: "602752456409826",
}
}
});
}
});
rustyApp.directive('animationOverlay', function() {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope, element, attrs) {
var modal = $.UIkit.modal(".modalSelector");
if (modal.isActive()) {
modal.hide();
} else {
modal.show();
}
}
});
UPDATED CODE
var rustyApp = angular.module('rustyApp', [
'ngAnimate',
'ngRoute',
'viewController',
'mm.foundation',
'angular-flexslider',
'ui.router'
]).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.when('/', {
title: 'home',
templateUrl: '/partials/home.html',
controller: 'HomeController'
}).when('/work', {
title: 'my work',
templateUrl: '/partials/work.html',
controller: 'WorkController'
}).when('/contact', {
title: 'contact',
templateUrl: '/partials/contact.html',
controller: 'ContactController'
}).otherwise({redirectTo: '/'});
// configure html5 to get links working
$locationProvider.html5Mode(true);
}]);
rustyApp.controller('BasicSliderCtrl', ['$scope',
function($scope) {
$scope.slides = [
'../images/sliderContent/1.jpg',
'../images/sliderContent/2.jpg',
'../images/sliderContent/3.jpg',
'../images/sliderContent/4.jpg'
];
}]);
rustyApp.run(function() {
FastClick.attach(document.body);
});
rustyApp.run(['$location', '$rootScope', function($location, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
$rootScope.title = current.$$route.title;
});
}]);
rustyApp.controller('HomeController', ['$scope', function($scope) {
$scope.pageClass = 'home';
}]);
rustyApp.controller('WorkController', ['$scope', function($scope) {
$scope.pageClass = 'work';
}]);
rustyApp.controller('ContactController', ['$scope', function($scope) {
$scope.pageClass = 'contact';
}]);
rustyApp.controller('OffCanvasDemoCtrl', ['$scope', function($scope) {}]);
var OffCanvasDemoCtrl = function($scope) {};
rustyApp.controller('ContactController', ['$scope', function($scope, $http) {
$scope.result = 'hidden'
$scope.resultMessage;
$scope.formData; //formData is an object holding the name, email, subject, and message
$scope.submitButtonDisabled = false;
$scope.submitted = false; //used so that form errors are shown only after the form has been submitted
$scope.submit = function(contactform) {
$scope.submitted = true;
$scope.submitButtonDisabled = true;
if (contactform.$valid) {
$http({
method: 'POST',
url: '../partials/mailer.php',
data: $.param($scope.formData), //param method from jQuery
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
} //set the headers so angular passing info as form data (not request payload)
}).success(function(data) {
console.log(data);
if (data.success) { //success comes from the return json object
$scope.submitButtonDisabled = true;
$scope.resultMessage = data.message;
$scope.result = 'bg-success';
if ($scope.result === 'bg-success') {
$scope.class = "bg-success";
}
// if($scope.result){setTimeout(window.location.reload(true),4000);}
if ($scope.result) {
setTimeout(function() {
window.location.reload(true)
}, 4000);
}
} else {
$scope.submitButtonDisabled = false;
$scope.resultMessage = data.message;
$scope.result = 'bg-danger';
}
});
} else {
$scope.submitButtonDisabled = false;
if ($scope.submitButtonDisabled) {
$scope.class = "bg-danger";
}
$scope.resultMessage = 'Failed Please fill out all the fields.';
$scope.result = 'bg-danger';
}
}
}]);
var viewController = angular.module('viewController', []);
rustyApp.directive('myActiveLink', ['$location', function($location) {
return {
restrict: 'A',
scope: {
path: "#myActiveLink"
},
link: function(scope, element, attributes) {
scope.$on('$locationChangeSuccess', function() {
if ($location.path() === scope.path) {
element.addClass('uk-active');
} else {
element.removeClass('uk-active');
}
});
}
};
}]);
// var $j = jQuery.noConflict();
// $j(function() {
// $j('#Container').mixItUp();
// });
rustyApp.directive('mixItUp', function() {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope, element, attrs) {
var $j = jQuery.noConflict();
var mixContainer = $j('#Container');
mixContainer.mixItUp();
mixContainer.on('$destroy', function() {
mixContainer.mixItUp('destroy');
});
}
});
rustyApp.directive('share', function() {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope, element, attrs) {
var $s = jQuery.noConflict();
// mixContainer.on('$destroy', function() {
// mixContainer.mixItUp('destroy');
// });
var $s = new Share(".share-button", {
networks: {
facebook: {
app_id: "602752456409826",
}
}
});
}
});
rustyApp.directive('animationOverlay', function() {
var directive = {
restrict: 'A',
link: link
};
return directive;
function link(scope, element, attrs) {
var modal = $.UIkit.modal(".modalSelector");
if (modal.isActive()) {
modal.hide();
} else {
modal.show();
}
}
});
UPDATE
So I wound using gulp-ng-annotateand it appears to add the syntax which was suggested below :) However when I try a PROD build I don't get any errors or anything, it just fails silently. Can anyone help?
I posted the generic answer below before I had a chance to see the rest of the code you posted. Yes, indeed you have some controllers and directives that use inference. Change your code to use inline annotation, the $inject property; or less intrusively, use a tool like ng-annotate (thanks #deitch for the pointer).
If you're minifying your code, don't use the inference style of dependency annotation. Use the $inject property or use inline annotation. See https://docs.angularjs.org/api/auto/service/$injector.
Example
Don't rely on inference:
function ($scope, $timeout, myFooService) {
}
Use either inline annotation:
[ '$scope', '$timeout', 'myFooService', function ($scope, $rootScope, myFooService) {
}]
Or the $inject property:
function MyFactory($scope, $timeout, myFooService) {
}
MyFactory.$inject = [ '$scope', '$timeout', 'myFooService' ];
This is because the inference flavour relies on the argument names of the function to be preserved (and match to existing services). You might be losing the original names during minification.
Set mangle: false.
This setting solved same problem that I had.
var $ = require('gulp-load-plugins')();
$.uglify({
mangle: false,
compress:true,
output: {
beautify: false
}
});
Do I have to move my getTemplates function out of the return or what ?
Example : I dont know what to replace "XXXXXXX" with (I have tried "this/self/templateFactory" etc... ) :
.factory('templateFactory', [
'$http',
function($http) {
var templates = [];
return {
getTemplates : function () {
$http
.get('../api/index.php/path/templates.json')
.success ( function (data) {
templates = data;
});
return templates;
},
delete : function (id) {
$http.delete('../api/index.php/path/templates/' + id + '.json')
.success(function() {
templates = XXXXXXX.getTemplates();
});
}
};
}
])
By doing templates = this.getTemplates(); you are referring to an object property that is not yet instantiated.
Instead you can gradually populate the object:
.factory('templateFactory', ['$http', function($http) {
var templates = [];
var obj = {};
obj.getTemplates = function(){
$http.get('../api/index.php/path/templates.json')
.success ( function (data) {
templates = data;
});
return templates;
}
obj.delete = function (id) {
$http.delete('../api/index.php/path/templates/' + id + '.json')
.success(function() {
templates = obj.getTemplates();
});
}
return obj;
}]);
How about this?
.factory('templateFactory', [
'$http',
function($http) {
var templates = [];
var some_object = {
getTemplates: function() {
$http
.get('../api/index.php/path/templates.json')
.success(function(data) {
templates = data;
});
return templates;
},
delete: function(id) {
$http.delete('../api/index.php/path/templates/' + id + '.json')
.success(function() {
templates = some_object.getTemplates();
});
}
};
return some_object
}
])