JavaScript Object Orientation Storing Multiple Items and Properties and Display - javascript

Would you be able to help me, I have been using a book and they have shown me a way to create an object in JavaScript and I have used there method but I am having trouble displaying it. My aim is to display it in a table using HTML 5 and I am going to create 9 more items to call upon and display. The book tells me to use product1.ShowDetails to display it but I have tried but having issues
Thank you for your time,
James
<script>
function Item(product, description, stockLevel, price)
{
this.Product = product
this.Description = description
this.Stock_Level = stockLevel
this.Price = price
this.showHeading = function()
{
document.write(this.product )
document.write(this.description)
document.write(this.stockLevel)
document.write(this.price)
}
this.showDetails = function()
{
document.write(this.product)
document.write(this.description)
document.write(this.stockLevel)
document.write(this.price)
}
product1 = new Item("Shorts (F)", "Stone Wash Dmin Shorts", 20, 25.90);
}

JavaScript properties are case sensitive. In your constructor you set this.Product to the product parameter but the showDetails() function references the this.product parameter.
Also, your code seems to have a typo, should the last bracket not be before product1 is declared?

Related

Why am I getting the Uncaught TypeError: Assignment to constant variable?

I am trying to create a vending machine app. I have created a class constructor in one file and used export so that I can import that into my other js file.
When I try and create a class object for the DrinkItem I get a Uncaught TypeError: Assignment to constant variable
please see the code below:
JS file 1 code
export class DrinkItem{
constructor(id, name, flavour,cost,stockAvailable){
this.id = id,
this.name = name,
this.flavour = flavour,
this.cost = cost,
this.stock = stockAvailable
}
}
JS file 2 code
import { DrinkItem } from "../classes/drinkItem.js"
/****************************
* Generates an ID for task *
****************************/
const createItemId = () => `${Math.floor(Math.random() * 1000)} - ${new Date().getTime()}`.value
//array for purchased drink item
let menu = [];
/*************************************************
* Create at least 5 different DrinkItem objects *
*************************************************/
DrinkItem = new DrinkItem(
createItemId,
"Fanta",
"grape",
18,
10
);
let test = DrinkItem.push(menu)
console.log(test)
The error happens at the new DrinkItem() bit, so maybe I am doing this incorrectly, I have looked at MDN, but it does not really explain it well, or maybe I miss understand it.
What am I doing wrong? I am using the class name DrinkItem for the const as I want it to link to the constructor.
What I want to do is create/instantiate at least 5 different DrinkItem objects inside of the menu array.
once the 5 DrinkItem objects are created I can push that into the menu array, but for now I am looking to see how to create the at least 1 object from the class.
Just the last piece of code:
You are assigning a value to a class
let drinkItem = new DrinkItem(
createItemId,
"Fanta",
"grape",
18,
10
);
Then here another error, menu is array and DrinkItem is object, push the last in the first one
let test = menu.push(drinkItem)
console.log(test)
Change to this:
let drinkItem = new DrinkItem( // DrinkItem variable name is already used for the class, you cannot give your instance the same variable name
createItemId(), // you want to call the function, not assign the function to DrinkItem.id
"Fanta",
"grape",
18,
10
);

angular checkboxes with 2 dimensional array

I have a template:
<mat-card *ngFor="let cargo of cargos" class="cont-mat">
/*...*/
<form [formGroup]="cargoSignupForm" (submit)="onSignupForCargo(cargo.id)" *ngIf="!isLoading">
<p>Odaberite kamione s kojima želite izvršiti prijevoz - Težina robe: {{cargo.weight}} kg</p>
<div *ngFor="let truck of (trucksByCargoId.get(cargo.id))">
<input type="checkbox" (change)="onChange(truck._id, $event.target.checked, cargo.id)">{{truck.regNumber}}
</div>
<input type="submit" value="GO" class="button-basic">
</form>
and 2 component functions:
truckFormArray = [[]];
ngOnInit() {
/*...*/
this.cargoSignupForm = new FormGroup({
trucksId: this.fb.array([])
});
/*...*/
}
onChange(truckId: string, isChecked: boolean, cargoId: string) {
this.truckFormArray[cargoId] = <FormArray>this.cargoSignupForm.controls.trucksId;
if (isChecked) {
this.truckFormArray[cargoId].push(new FormControl(truckId));
} else {
let index = this.truckFormArray[cargoId].controls.findIndex(x => x.value == truckId)
this.truckFormArray[cargoId].removeAt(index);
}
}
onSignupForCargo(cargoId: string) {
console.log(this.truckFormArray[cargoId]);
}
I just want to console_log(this.truckFormArray[cargoId]). There must be different truckFormArray for every cargoId. With that solution I'm getting trucksFormArray from previus cargoId checkboxes also. I hope you understand what I mean. Somewhere is a small mistake, but also if you think there is a better solution to do that you are welcome. Thanks in advance
truckFormArray should be an object
It is safe to assume that cargoId is not a sequentially increasing number starting from 0, hence there is no sense in declaring it as an array, declare it as an object instead:
truckFormArray = {};
Reason: Arrays in Javascript are always indexed by numbers starting from 0 and increasing sequentially until the last index.
truckFormArray is not a data member of the instance of your object
Since it is not initialized as this.truckFormArray, you do not have the this in front of it. So change all occurrences of this.truckFormArray to truckFormArray.
Reason: You will always need to be consistent when you refer to your resources.
Initializing truckFormArray
You have
this.truckFormArray[cargoId] = <FormArray>this.cargoSignupForm.controls.trucksId;
and it seems to be incorrect. Your trucksId seems to be a number and you try to assign it to a resource which is treated as an array, so there is a type discrepancy. If you want to store each trucksId into an array identified by the cargo that is present on the trucks, then you need to do a push, but only if the checkbox is checked. So, instead of the above, you will need something like this:
if (!truckFormArray[cargoId]) {
//Here I created a JS array for the sake of simplicity, but you can
//create a FormArray instance instead if that's more helpful for you
this.truckFormArray[cargoId] = [];
}
Reason: if the array you need to refer to does not exist yet, then you need to create it.
Summary
You will need to
fix the initialization of truckFormArray
ensure that you refer it consistently with the way it is defined
initialize each of its cargo array when needed

Checking an input against a specific array string

I am trying to create a quiz that randomly selects a question from pool of questions in an array, which is answered in an input box that is to be checked against the corresponding answer string in the array. I used math.floor(math.random() *); to get my random number. The random number is intended to be used to find both the question and answer, which are arranged in order to correspond to one another, e.g. ['question1','question2'] and ['answer1','answer2'].
I am having difficulty with trying to get my input to properly be checked against the corresponding answer value from the array. I am fairly novice at Javascript, so I am not sure as to how to do this. I tried using the document.getElementById command to compare the two. I suspect it has something to do with the fact that ansNum doesn't get the value of questNum because of the fact that questNum is only given its value inside the generateQuiz function. (I realize ansNum is likely redundant, but I was just playing around to see if anything would happen)
Javascript:
const questions = ['What do young Roman males wear?','Who is the Roman god of the smith?','Who is the 6th king of Rome?'];
const answers = ['toga praetexta','vulcan','servius tullius'];
function getQuestNum() {
questNum = Math.floor(Math.random() * 3);
};
function getAnsNum() {
ansNum = questNum();
}
function generateQuiz() {
getQuestNum();
document.getElementById("question").innerHTML = questions[questNum];
};
function checkCorrect() {
getAnsNum();
if (answer[ansNum] = document.getElementById("input").innerHTML) {
document.getElementById("verification").innerHTML = "Correct!";
}
};
Codepen Link
An image of the code
Based on your code, I fixed it with some changes. It is not the best way to do this i think. I posted the js part here.
const questions = ['What do young Roman males wear?','Who is the Roman god of the smith?','Who is the 6th king of Rome?'];
const answers = ['toga praetexta','vulcan','servius tullius'];
var questNum;
function getQuestNum() {
questNum = Math.floor(Math.random() * 3);
};
function getAnsNum() {
ansNum = questNum;
}
function generateQuiz() {
getQuestNum();
document.getElementById("question").innerHTML = questions[questNum];
};
function checkCorrect() {
getAnsNum();
if (answers[ansNum] = document.getElementById("input").value) {
document.getElementById("verification").innerHTML = "Correct!";
}
};
First you need a global variable questNum then you can use it in all of your functions.
The function getAnsNum() is redundant, at least i think so, just use questNum in your checkCorrect() function.
For getElementByID function, insert an ID attribute to your input
<input id="input" type="text" name="input">
For input, if you want to take the value of the input field, use document.getElementById("input").value instead of innerHTML.
If you not sure about any result, console.log it or use Chrome dev debug tool to check the result. In the checkCorrect function, your array name should be answers instead of answer.
Shorter ver:
const questions = ['What do young Roman males wear?','Who is the Roman god of the smith?','Who is the 6th king of Rome?'];
const answers = ['toga praetexta','vulcan','servius tullius'];
var questNum;
function getQuestNum() {
questNum = Math.floor(Math.random() * 3);
};
function generateQuiz() {
getQuestNum();
document.getElementById("question").innerHTML = questions[questNum];
};
function checkCorrect() {
if (answers[questNum] = document.getElementById("input").value) {
document.getElementById("verification").innerHTML = "Correct!";
}
};
It would be simpler to create an array of objects that each contain both a question and an answer - and create a function that generates your random number and returns the object at the corresponding index.
Then you'll have access to everything you need without worrying about whether or not you can maintain access to the original randomly selected number, or matching up indices between two different arrays.

value not binding with array object

I have an app that deals with ordering coffee. The coffee store has a table that shows drink types by size, and they can click on a given drink/size and edit data about that drink/size combo, such as the price.
Before, there was a set list of coffee drinks (mocha, cappuccino, etc) and I was able to gasp hardcode the drinks and get by this bug. However, things have changed and now the store can add custom drinks, meaning that I can no longer hardcode the drinks and I need to get the store drinks from the API.
This project is using Ember 1.13, and I'm setting the drinks in the setupController in the route. In this example I'm not going to be showing the custom drinks, the problem is reproducible just by using the default drinks.
model: function() {
let myStoreId = this.controllerFor('application').get('myStore.id');
return Ember.RSVP.hash({
myStore: this.store.find('store', myStoreId),
storeDrinks: this.store.find('store-drink', {'store':myStoreId}),
...
});
},
setupController: function(controller, model) {
// we have some set drinks that will be for every store, although they can set inactive
let defaultDrinks = [
"Americano", "Capuccino", "Drip", "Espresso", "Latte", "Mocha", "Tea"
];
let drinksArray = [];
let drinkType, keyName;
let pluralize = function(string){
// return plural and lower case for a drink type
let lower = string.toLowerCase();
let plural = lower + "s";
return plural;
};
for (let i = 0; i < defaultDrinks.length; i++) {
drinkType = defaultDrinks[i];
keyName = pluralize(drinkType);
// when we define like this, there are bugs editing in the template. But we
// can loop though all the drinks by type. I can get a list of custom drinks
// from the API and add those into the loop.
drinksArray[keyName] = this.store.filter('store-drink', function(drink) {
return drink.get('type') === drinkType;
});
}
// when we define like this (hardcode), it works fine in template but we
// can't keep doing this because with custom drinks we don't know the type
// when we get the above loop working, this code will be gone, but it shows
// what works in the template to edit drinks.
let cappuccinos = this.store.filter('store-drink', function(drink) {
return drink.get('type') === "Cappuccino";
});
...
console.log(drinksArray["mochas"], cappuccinos);
controller.setProperties({
'mochas': drinksArray["mochas"],
'cappuccinos': cappuccinos,
...
'myStore': model.myStore,
});
}
There's the setup in the route. Now in the template I have an input that is tied to the drink value. When they click on one of the drink/size combos, it opens a div that has the detailDrink object. {{input value=detailDrink.price ... }}.
When the drink uses the drinkList in the form of cappuccino everything works fine. When the drink uses the drinkList in the form of drinksArray["mochas"] then when the input changes, there are various bugs. I don't believe the details of this part to be significant but sometimes it deletes the cell value, sometimes it doesn't reflect the change, and sometimes it binds multiple cells to the same value. The issue is that when using the data from an array (such as with mochas) this bug is there, and when using the hardcoded value (such as with cappuccinos) the drink data can be updated correctly.
Another thing to note is that in the console.log(drinksArray["mochas"], cappuccinos); above, both objects appear to be the same, other than of course one is a list of cappuccinos and the other is a list of mochas.
I've literally been stuck on this for months off-and-on, and have tried so many things and have isolated it down to this.
EDIT ADDITION:
You might think "how will this help your problem"? My idea is to have an array of objects such as:
[{
'drinkSet': cappuccinos,
'drinkType': 'Cappuccino',
}, {
'drinkSet': mochas,
'drinkType': 'Mocha',
},
{
'drinkSet': myCustomWhiteChocolateThunder,
'drinkType': 'White Chocolate Thunder',
},
...
]
and then loop through my template table rows with each drink type
<table class="table table-striped menu__drink-table hidden-xs">
<thead>
<tr>
<th>Drink</th>
<th>8oz</th>
<th>12oz</th>
<th>16oz</th>
<th>20oz</th>
<th>24oz</th>
<th>32oz</th>
</tr>
</thead>
<tbody>
{{#each drinkSetObject in drinkSets}}
{{joe-menu-row drinkSet=drinkSetObject.drinkSet type=drinkSetObject.drinkType detailDrink=detailDrink}}
{{/each}}
</tbody>
</table>
I had this before, but isolated the problem down to the fact that when the drinks were a value in an array for some reason they don't work as they do when declaring the variable directly.
I had similar problem resolving promises in setup controller. Seems that promise in an array does not resolve so you can't get the data in the template.
Please try the next and let me know:
for (let i = 0; i < defaultDrinks.length; i++) {
// can't be method variables since will be used in the promise
let drinkType = defaultDrinks[i];
let keyName = pluralize(drinkType);
this.store.filter('store-drink', function(drink) {
return drink.get('type') === drinkType;
}).then(function(result) {
controller.set(keyName, result);
}, function(error) {
//TODO: handle error
});
}
Also, use the ember inflector's pluralize function:
const { Inflector: { inflector } } = Ember
let keyName = inflector.pluralize(drinkType);
Hope it helps
ps: dont forget to remove the controller.setProperties setup

Add another value to nested javascript object?

I have the following JavaScript object, with a property called rates, which contains another object with the actual rates. Now I want to add a new rate "CAD":0.972254 to the rates. How can I add this one value to the list?
var Currency = {
rates: {"USD":1.0,"EUR":1.3497,"GBP":1.60403},
convert: function(amount, from, to) {
return (amount * this.rates[from]) / this.rates[to];
}
};
You can do it either way
Currency['rates']['CAD'] = 0.972254;
Or,
Currency.rates.CAD = 0.972254
Fiddle Here
You can assign a new property to existing object like:
Currency.rates.CAD = 0.972254
Currency.rates.CAD = 0.972254;

Categories

Resources