Injecting factories into controllers with angular js - javascript

I am working to get a deeper understanding of factories and constructors. I am a bit confused however about where to put the instances and how to print them out. I am getting back Plate is not defined.
Here is how I have configured my js file
var app = angular.module('dinerApp', ['ngRoute']);
app.config(function($routeProvider){
$routeProvider.when('/basque',{
templateUrl:"./client/app.html",
controller: 'AppCtrl'
})
.when('/menu',{
templateUrl:"./client/menu.html",
controller:'MenuCtrl'
})
.otherwise({
redirectTo: '/basque'
});
});
Here is my factory I have placed the constructor and its prototype in the factory. I am working to make a basic restaurant menu.
app.factory('diner', function($q,$http){
var Plate = function(name, description, price, ingredients){
this.name = name;
this.description =description;
this.price = price;
this.ingredients = ingredients;
};
Plate.prototype.toString= function(){
var returnString='' ;
returnString += "name" + this.name + "\n" +
"description: " + this.description + "\n" +
"price: " + this.price + "\n";
return returnString;
};
return Plate;
})
Below is my controller. I have created a few instances.
app.controller('MenuCtrl',function($scope,diner){
var steakSandwich= new diner.Plate('Steak Sandwich', 'Something nice and tasty', 11.75);
var lambShoulderSteak = new Plate('Lamb Shoulder Steak','Something Different', 11.75);
var lambChops = new Plate('Lamb Chops', 'why not', 14.75);
var chickenSandwich = new Plate('chicken Breast Sandwich', 'basque chicken on a bun',9.75);
var basqueBurger = new Plate('Basco Burger', 'a better burger', 9.75);
$scope.plates = diner.Plate;
});
In my html I would ideally be calling ng-repeat
<ul ng-repeat="plate in plates">
<li>{{plate.name}} </li>
<li>{{plate.description}}</li>
<li>{{plate.price}}</li>
</ul>

Dylan is right. You messed up with your namespaces of your factory. Get proper objects and put them to the scope like this.
working plunkr of your factory
app.factory('Plate', function(){
var Plate = function(name, description, price, ingredients){
this.name = name;
this.description =description;
this.price = price;
this.ingredients = ingredients;
};
Plate.prototype.toString= function(){
var returnString='' ;
returnString += "name" + this.name + "\n" +
"description: " + this.description + "\n" +
"price: " + this.price + "\n";
return returnString;
};
return Plate;
})
app.controller('MainCtrl', function($scope, Plate) {
var steakSandwich= new Plate('Steak Sandwich', 'Something nice and tasty', 11.75);
var lambShoulderSteak = new Plate('Lamb Shoulder Steak','Something Different', 11.75);
var lambChops = new Plate('Lamb Chops', 'why not', 14.75);
var chickenSandwich = new Plate('chicken Breast Sandwich', 'basque chicken on a bun',9.75);
var basqueBurger = new Plate('Basco Burger', 'a better burger', 9.75);
var diner = [];
diner.push(steakSandwich, lambShoulderSteak,lambChops,chickenSandwich,basqueBurger);
$scope.plates = diner;
angular.forEach(diner, function (plate) {
console.debug(plate.toString());
});
});
Checkout the console to check your toString().

You're returning Plate from your factory, therefor diner is Plate, it does not have a property Plate. You should either call your factory "Plate" and new it up directly, or return an object with a Plate property.

Related

Object constructor syntax error

In the process of learning JS... it's mai second week from the first day of JS and i have that big problems with syntax
function Customer(name, street, city, state, email, balance) {
this.name = name;
this.street = street;
this.city = city;
this.state = state;
this.email = email;
this.balance = balance;
this.payDownBal = function(amtPaid) {
this.balance -= amtPaid;
};
this.addToBa = function(amtCharged) {
this.balance += amtCharged;
};
}
var cust2 = new Customer("Sally Smith", "234 Main ", "Pittsburgh", "PA", "ssmith#aol.com", 0.00);
cust2.addToBal(15.50);
Customer.prototype.isCreditAvail = true;
Customer.prototype.toString = function() {
return this.name + " lives at " + this.street + " in " +
this.city + " " + this.state + " email : " + this.email +
" and has a balance of $ " + this.balance.toFixed(2) + "Creditworty : " + this.isCredAvail;
}
document.write(cust2.toString());
I can't find the error...can i be helped please ?
You made a simple mistake.
You defined addToBa() function and you are calling function addToBal() which is not defined.
Change the line 17 to call the function addToBa(). (or change the function declaration to addToBal()).
Well, look at line 11 closely, your function declaration:
this.addToBa = function (amtCharged) {
and line 17:
cust2.addToBal(15.50);
It's a typo, "addToBa" on line 11 should be "addToBal".
(Also, there's another typo that won't allow the "isCreditAvail" TRUE boolean value to be referenced in your toString function, on the 3rd-to-last line... change "this.isCredAvail" to "this.isCreditAvail").

How do I create a new instance in a factory

I cannot figure out how to create a new instance in my factory. I created a constructor in the initial factory
app.factory('Tea',function(){
var Tea = function(name,description,price,caffeine, size ) {
this.name = name;
this.description = description;
this.price = price;
this.caffeine = caffeine;
this.size = size;
}
Tea.prototype.toString = function(){
var returnString='' ;
returnString += "name" + this.name + "\n" +
"description: " + this.description + "\n" +
"price: " + this.price + "\n" + "caffeine: " + this.caffeine + "\n" + "size: " + this.size;
return returnString
}
return Tea;
})
In my next factory I made sure to inject Tea so I would be able to create new instances. I created an object to store my array and created a method to push new instances
app.factory("DrinkList",function(Tea){
var beverageList = {
drinkLibrary: []
};
beverageList.newItem = function(){
beverageList.drinkLibrary.push(new Tea);
}
console.log(beverageList);
return beverageList;
})
In my controller I made sure to reference both factories that I created. However, drinkList.newItem is undefined.
app.controller('myController', function($scope,Tea,DrinkList ) {
$scope.drinkList = DrinkList.newItem();
console.log(DrinkList.newItem());
});
I have been working hard to get a better grasp of factories and controllers.
In my Factory I have created an instance
app.factory('Drink',function($http) {
var Drink = function(name,description,caffeineLevel) {
this.name = name;
this.description = description;
this.caffeineLevel = caffeineLevel;
}
return Drink;
})
This needs some cleaning up, but I realized that I need to use ng-model in my form. I have declared a form that can be reused and stored it inside of a function. I am creating new instances each time I click submit. There is more that I need to learn but this is a start.
app.controller('myController', function($scope,Drink,$http ) {
var init = function() {
$scope.defaultForm = {
beverageName: "",
description: "",
caffeine: ""
};
}
init();
// $scope.defaultForm = defaultForm;
$scope.allDrinkList = [];
$scope.drinkList= function(obj) {
var newdrink = new
Drink(obj.beverageName,obj.description,obj.caffeine);
$scope.allDrinkList.push(newdrink);
console.log($scope.allDrinkList);
init();
});

Javascript prototype handling self and constructor parameters

Im trying to understand javascript prototyping principles and cant get some basic things to work.
One thing that im trying to achieve is, to create a base object, that handles constructor input, and sets values based on that input, or default values if no constructor parameter is given.
Also, i cant quite figure out how to store this this in a variable so that it would point to correct instance of the object( parent object perhaps )
Below are 2 versions which i have tried to create basic inheritance. ( first one ive seen used before, but it doesnt allow me to handle constructor parameters passed to extended object using its base object's constructor.
The second version...is something i came up with to enable it, but...i have never seen anyone using prototypes like this and im sure its the wrong way ( since the prototype property is a function instead of an object)
Whats the correct way of solving both of the problems.
var Person = function(conf) {
if (!conf) {conf = {};}
var _person = this;
this.first_name = conf.first_name;
this.last_name = conf.last_name;
this.greet = function() {
alert("Hi, im " + this.first_name + " " + this.last_name );
}
this.callback_greet = function() {
alert("Hi, im " + _person.first_name + " " + _person.last_name );
console.log("this:", this, " _person:", _person );
}
}
var Student = function(conf) {
if (!conf) {conf = {};}
/* id like to pass this conf on to Person constructor */
this.report = function() {
alert( this.first_name + " " + this.last_name + " is ready to study" );
}
}
Student.prototype = new Person();
var Teacher = function(conf) {
if (!conf) {conf = {};}
this.teach = function() {
alert( this.first_name + " " + this.last_name + " is ready to teach...maggots" );
}
}
Teacher.prototype = new Person();
student = new Student({first_name: "Mike", last_name: "Stud"});
//student.first_name="Mike";
//student.last_name="Stud";
student.greet();
/* alerts Hi, im Mike Stud */
teacher = new Teacher();
teacher.first_name="John";
teacher.last_name="Smith";
teacher.teach();
/* alerts John Smith is ready to teach...maggots */
teacher.callback_greet ();
/* both alerted values are undefined */
//_________________________
//_______Version 2 _______
//_________________________
var Person = function(conf) {
if (!conf) {conf = {};}
var _person = this;
this.first_name = conf.first_name;
this.last_name = conf.last_name;
this.greet = function() {
alert("Hi, im " + this.first_name + " " + this.last_name );
}
this.callback_greet = function() {
alert("Hi, im " + _person.first_name + " " + _person.last_name );
console.log("this:", this, " _person:", _person );
}
}
var Student = function(conf) {
if (!conf) {conf = {};}
this.prototype = Person;
this.prototype(conf);
this.report = function() {
alert( this.first_name + " " + this.last_name + " is ready to study" );
}
}
var Teacher = function(conf) {
if (!conf) {conf = {};}
this.prototype = Person;
this.prototype(conf);
this.teach = function() {
alert( this.first_name + " " + this.last_name + " is ready to teach...maggots" );
}
}
var Principal = function(conf) {
if (!conf) {conf = {};}
this.prototype = Teacher;
this.prototype(conf);
this.dicipline_teachers = function() {
alert( this.first_name + " " + this.last_name + " thy all mighty principal is watching you" );
}
}
student = new Student({first_name: "Mike", last_name: "Stud"});
student.greet();
/* alerts Hi, im Mike Stud */
teacher = new Teacher({first_name: "John", last_name: "Smith"});
teacher.teach();
/* alerts John Smith is ready to teach...maggots */
principal = new Principal({first_name: "David", last_name: "Faustino"});
principal.teach();/* alerts David Faustino is ready to teach...maggots */
principal.dicipline_teachers();/* David Faustino thy all mighty principal is watching you*/
Well, your second version is actually… somewhat… correct!
What your snippet
var Student = function(conf) {
this.prototype = Person;
this.prototype(conf);
does here:
Have a Student instance as this when being invoked with new Student()
Create a property on the instance that contains a function (in this case, the parent constructor), which essentially creates a method on the instance
Call that as a method. Which means, the Person function is invoked with its this pointing to the instance that we have here - and then Person does its setup on that instance.
This is just what we want. Maybe except for creating the unnessary property. Notice that the name of this property being prototype is totally irrelevant for its function, you could have use myParentConstructor or so as well.
In the standard JavaScript inheritance, we do a similar thing to that method call - we want to call the parent constructor on the current (child) instance so that it does get set up. However, we use the .call() method for that.
Now we also want to use the prototype. In your code, all the methods greet, report, teach and dicipline_teachers could be shared amongst the instances, so they can - and should - go on the ConstructorFn.prototype. To let all teachers, students, and principals inherit these methods we need to set up a prototype chain (inheritance hierarchy). We don't want to use new Person as that would call the constructor and set up things like first_name on the prototype object where they would to be shared - but we don't want that. Instead, we use Object.create.
Alltogether, your code would look like this:
function Person(conf) {
if (!conf) {conf = {};}
var _person = this;
this.first_name = conf.first_name;
this.last_name = conf.last_name;
this.callback_greet = function() {
alert("Hi, im " + _person.first_name + " " + _person.last_name );
console.log("this:", this, " _person:", _person );
};
}
Person.prototype.greet = function() {
alert("Hi, im " + this.first_name + " " + this.last_name );
};
function Student(conf) {
Person.call(this, conf);
}
Student.prototype = Object.create(Person.prototype, {constructor:{value:Student}});
Student.prototype.report = function() {
alert( this.first_name + " " + this.last_name + " is ready to study" );
};
function Teacher(conf) {
Person.call(this, conf);
}
Teacher.prototype = Object.create(Person.prototype, {constructor:{value:Teacher}});
Teacher.prototype.teach = function() {
alert( this.first_name + " " + this.last_name + " is ready to teach...maggots" );
};
function Principal(conf) {
Teacher.call(this, conf);
}
Principal.prototype = Object.create(Teacher.prototype, {constructor:{value:Principal}});
Principal.prototype.dicipline_teachers = function() {
alert( this.first_name + " " + this.last_name + " thy all mighty principal is watching you" );
};
(1) It's best to handle setting default values after a proper sanity check on the type(s) of value(s) passed:
var Constr = function (conf) {
if (!!conf && !(conf instanceof Object)) {
throw new Error('An invalid parameter was passed to Constr.');
}
if (!conf) { // Prevent "Can't read property 'name' of undefined."
conf = {};
}
this.name = conf.name || null; // Set defaults this way.
};
(2) You'll want to use Object.create() and Object.apply() to get this right:
var Person = function (param1, param2) {
this.param1 = param1;
this.param2 = param2;
}
Person.prototype.cough = function () {
// Do stuff.
}
var Student = function (param1, param2, paramN) {
Person.call(this, param1, param2);
this.paramN = paramN; // Define a new property on the subclass
}
// Invoke the superclass to have the subclass inherit properties and methods.
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

Is possible to bind a function result with angularJS?

I have this object:
function Boy(n,s,a)
{
this.name = n;
this.surname = s;
this.age = a;
this.getInfo = function(){
return this.name + ' ' + this.surname + ' (' + this.age + ')';
}
}
I want to do something like this:
{{ boy.getInfo() }}
and not like this:
{{ boy.name }} {{ boy.surname }} ({{boy.age}})
is it possible?
there are some tricks for doing something similar?
Absolutely! You can create an object and shove it into $scope just like anything else.
var NameController = function ($scope) {
$scope.boy = new Boy("Foo", "Bar", 32);
};
NameController.$inject = ['$scope'];
app.controller("NameController", NameController);
And then bind it in the UI just like so:
<h3>{{boy.getInfo()}}</h3>
Here is an example of binding to all three properties and seeing the result of the function: http://jsfiddle.net/jwcarroll/Pb3Cu/
You can bind $scope functions normally
function MyController($scope){
$scope.myfunc = function(){
return "test";
}
}
and then, in the view
{{ myfunc() }}
You can do something like:
function Boy(n,s,a)
{
this.name = n;
this.surname = s;
this.age = a;
this.getInfo = function(){
return this.name + ' ' + this.surname + ' (' + this.age + ')';
}
}
var boy = new Boy(n, s, a);
$scope.boy = function(){
return boy.getInfo();
}
And in you template just bind {{boy()}}.

JavaScript prototyping not working

I am following an online tutorial and I am at a prototype section. My alert comes back with
function() { return this.brand + ' ' + this.model; }
Anyone know the reason?
function Car(model, brand) {
this.model = model;
this.brand = brand;
}
Car.prototype.fullName = function() {
return this.brand + ' ' + this.model;
}
var s = new Car("G5", "Pontiac");
var full = s.fullName;
alert(full);
s.fullName is the function itself. If you wanted to call this function you would have to write s.fullName().

Categories

Resources