Angular - Only push to array if unique - javascript

I have an Angular application that collects values of items for an invoice, I want to make sure only unique items are being added to this collection but am having no luck.
I am pushing 3 pieces of information to this collection: id, price, and type. I want to make sure there is nothing in the collection currently matching those 3 points.
// My container
$scope.invoice = {
items: [{
}]
}
$scope.addPhoto = function() {
console.log('Withdrawing Photo: '+ $scope.item.id);
if ($scope.invoice.items.indexOf(item.id) != $scope.item.id)
{
$scope.invoice.items.push({
id: $scope.item.id,
price: $scope.item.price,
type: 'photo'
});
}
}
// Trying to avoid collections like this
invoice: {
items:
[ { } , {
id: 25
price: 0
type: photo
} , {
id: 25
price: 0
type: photo
} ]
}

.filter is pretty much what you need.
$scope.addPhoto = function() {
console.log('Withdrawing Photo: '+ $scope.item.id);
var matches = $scope.invoice.items.filter(function(datum) {
return datum.id === $scope.item.id &&
datum.price === $scope.item.price &&
datum.type === $scope.item.type;
});
if (!matches.length)
{
$scope.invoice.items.push({
id: $scope.item.id,
price: $scope.item.price,
type: 'photo'
});
}
}
Semi-contrived JSFiddle

This is the solution I came up with to solve my problem, hopefully it helps someone else.
$scope.addPhoto = function () {
console.log('Withdrawing Photo: ' + $scope.item.id);
var newItemId = $scope.item.id;
var newItemPrice = $scope.item.price;
var newItemType = 'photo';
var matches = true;
// Make sure user hasnt already added this item
angular.forEach($scope.invoice.items, function(item) {
if (newItemId === item.id && newItemPrice === item.price && newItemType === item.type) {
matches = false;
$scope.message = 'You have already selected to withdraw this item!';
}
});
// add item to collection
if (matches != false) {
$scope.invoice.items.push({
id: $scope.item.id,
price: $scope.item.price,
type: 'photo'
});
$scope.total += $scope.item.price;
$scope.message = 'Total Amount Selected';
}
};

YOu can simple pop opposite of push
array.splice(array.pop(item));

Related

MongoDB if statement in a parameter

I am trying to not make my code redundant and I would like to know, if in a .updateOne method, when Im passing data to change, if its possible to implement if statement to choose from the data. Here is a situation.
I have my db model:
const depositarySchema = new Schema({
euid: {
type: String,
required: true
},
euid2: {
type: String
},
count: {
type: Number,
required: true
},
euroPallets: {
type: Number,
},
biggerPallets: {
type: Number,
},
otherPallets: {
type: Number,
},
depositary: {
type: Number,
required: true
},
title: {
type: String
}
});
Then I have a variable: var = 1 for euroPallets, 2 for biggerPallets and 3 for otherPallets. I would like to implement something like this:
Depositary.updateOne(
{
euid: euid,
},
{
count: dep.count - palletCounter,
if(var === 1){
euroPallets: count}
elseif(var===2){
biggerPallets: count}
else{
otherPallets: count}
},
where count is just a number. I hope its understandable what im trying to achieve, sorry for a wrong syntax.
Wernfried Domscheit beat me to it, but I will post my answer anyways.
const palletTypes = ['otherPallets', 'euroPallets', 'biggerPallets'];
var count = ep.count - palletCounter;
var palletType = palletTypes[count] || palletTypes[0];
var pallets = {'count': count};
pallets[palletType] = count;
Depositary.updateOne(
{euid: euid},
pallets
)
I would honestly just make a helper method so you can just send in parameters and it will turn everything to the correct objects.
updatePallets(euid, ep.count, palletCounter)
Maybe this one:
let upd = {
euid: euid,
count: dep.count - palletCounter
};
if (var === 1) {
upd['euroPallets'] = count;
}
else if (var === 2) {
upd['biggerPallets'] = count;
}
else {
upd['otherPallets'] = count;
}
Depositary.updateOne(upd)
EDIT:
For .updateOne() method to actually work like I want to, you need to separate the euid parameter. The correct solution is this:
let upd = {
count: dep.count - palletCounter
};
if (var === 1) {
upd['euroPallets'] = count;
}
else if (var === 2) {
upd['biggerPallets'] = count;
}
else {
upd['otherPallets'] = count;
}
Depositary.updateOne(
{
euid: euid,
},
upd,
)

Setting Correct Boolean Conditions

I am working on practicing booleans (where in the code below, I'm representing the number of times a fruit is counted, essentially that number will be what they can afford to the price, if that makes sense) and the code I am working on seems to be working, but the conditionals I have set are only returning as false and not as true and vice versa when they are swapped.
I'm just wondering if there is an issue with the logic that I currently have.
Here is the data that I have:
items = {
count: 100,
fruits: [
{ id: 'apple', price: 50 },
{ id: 'orange', price: 200 },
{ id: 'banana', price: 500 }
]
};
});
('returns true if the person can afford the item', function() {
const result = code.affordItem(items, 'apple');
expect(result).to.be.equal(true);
});
('returns false if person cannot afford the item', function() {
const result = code.affordItem(items, 'orange');
expect(result).to.be.equal(false);
Here is the code that I have:
function affordItem(items, itemId) {
if (items.count >= items.fruits.quantity && items.fruits.id === itemId) {
return true;
} else {
return false;
}
}
Any guidance would be much appreciated!
function affordItem(items, itemId) {
if (items.count >= items.fruits.length && items.fruits.id === itemId) {
return true;
} else {
return false;
}
}
Try this, i assumed you want to get the quantity of fruits so use array.length instead.

How can I access to the if with an array of objects?

Hello I'm new in JS and I need to test the if.
const length = notifications.length
notifications.forEach((notification, index) => {
if (length > 1 && index < length - 1) {
toolTipText += ' '
}
In other words I need to declare a variable to enter the if. I have these variable but is wrong and I don't know how to do it well
const mockPropsForComponentAlternatorAndLOW = {
notifications: [{
params: {
subType: 'ALTERNATOR'
}
},
params: {
subType: 'LOW'
}]
}
Any suggestions?
Your script works. Just remove some syntax mistakes and point to the right reference:
mockPropsForComponentAlternatorAndLOW.notifications.length
const mockPropsForComponentAlternatorAndLOW = {
notifications: [
{
params: {
subType: 'ALTERNATOR'
}
},
{
params: {
subType: 'LOW'
}
}
]
}
const length = mockPropsForComponentAlternatorAndLOW.notifications.length
mockPropsForComponentAlternatorAndLOW.notifications.forEach((notification, index) => {
if (length > 1 && index < length - 1) {
alert('in the scope now')
// toolTipText += ' '
}
})
I'm not 100% sure what you're asking, but I'm going to interpret this as "my code isn't running, what's wrong with it?". There's a syntax error in your mockPropsForComponentAlternatorAndLOW variable. There needs to be a "{" and "}" around the second "notification" object, like this:
const mockPropsForComponentAlternatorAndLOW = {
notifications: [{
params: {
subType: 'ALTERNATOR'
}
},
{
params: {
subType: 'LOW'
}
}]
}
Your question is fairly vague, but if I assume you're building toolTipText by appending notification text and you want a space between each notification text, the minimal change would be to test index > 0 && index < length rather than length > 1 && index < length - 1:
let toolTipText = "";
const length = notifications.length;
notifications.forEach((notification, index) => {
if (index > 0 && index < length) {
toolTipText += ' '
}
toolTipText += notification.text; // Or whatever the property is called
});
Live Example:
function buildToolTipText(notifications) {
let toolTipText = "";
const length = notifications.length;
notifications.forEach((notification, index) => {
if (index > 0 && index < length) {
toolTipText += ' '
}
toolTipText += notification.text; // Or whatever the property is called
});
return toolTipText;
}
console.log(buildToolTipText([{text: "only"}]));
console.log(buildToolTipText([{text: "first"}, {text: "second"}]));
console.log(buildToolTipText([{text: "first"}, {text: "second"}, {text: "third"}]));
but, you may find it simpler to use map and join:
let toolTipText = notifications.map(n => n.text).join(" ");
Live Example:
function buildToolTipText(notifications) {
let toolTipText = notifications.map(n => n.text).join(" ");
return toolTipText;
}
console.log(buildToolTipText([{text: "only"}]));
console.log(buildToolTipText([{text: "first"}, {text: "second"}]));
console.log(buildToolTipText([{text: "first"}, {text: "second"}, {text: "third"}]));

Skip json object (PHP session)

I have an array of users. Each user can be skipped on .click button. However I want it to skip the user that logs in. The session is started with PHP, but I'm showing the user through ajax and javascript. However
if(sSession = sKey){
aPeople.slice(this.jPerson);
}
is not correctly skipping the user. Could you help?
Here's the code:
$("#btnSkip").click(function() {
$.getJSON('include/users.txt', function(aPeople){
var getPerson = function(id) {
var jPerson = aPeople[id]
var sID = jPerson.id
var sName = jPerson.name
var sImage = jPerson.picture
var sSession = $('#mySession').text()
var sKey = jPerson.key
//this if statement doesn't work
if(sSession == sKey){
console.log(sSession)
console.log(sKey)
console.log(personIndex)
console.log(jPerson)
aPeople.splice(jPerson);
}
$('#sName').text(sName)
$('#sImg').attr('src', sImage)
//TO START COUNT AGAIN
if(aPeople.length -1 == personIndex){
personIndex = 0
}else{
personIndex = personIndex + 1
}
}
getPerson(personIndex);
$( '#sName' ).fadeIn( 'slow' )
$( '#sImg' ).fadeIn( 'slow' )
})
})
So, it looks to me like to you want to:
Retrieve an array of user objects.
Navigate the retrieved list and display each user on a button click.
Never display the logged in user.
Here's a suggested solution:
I'm filtering out the logged in user with the jQuery grep function.
I simplified your navigation logic.
I wasn't sure you meant to retrieve the users JSON on every click, so I altered that also.
function setupUserNavigator(users, loggedInUserKey) {
var idx = 0;
// filter out the logged in user
var filtered = $.grep(users, function(user) {
return !(user.key === loggedInUserKey);
});
function current() {
return filtered[idx];
}
function next() {
idx += 1;
}
function more() {
return idx < filtered.length - 1;
}
return { current, next, more };
}
function displayUser(user) {
$('#sName').text(user.name);
$('#sImg').attr('src', user.picture);
}
function usersResponseHandler(users) {
var loggedInUserKey = $('#mySession').text();
var userNavigator = setupUserNavigator(users, loggedInUserKey);
// display the first user immediately
displayUser(userNavigator.current());
// display each subsequent user on a 'next' button click
$('#next').click(function() {
userNavigator.next();
displayUser(userNavigator.current());
if(!userNavigator.more()) {
$(this).prop('disabled', true);
}
});
}
// $.getJSON('include/users.txt', usersResponseHandler);
// use test data for the snippet and mock response handler call
var data = [
{ id: '1', key: '1234', name: 'Joe', picture: 'img/joe.png' },
{ id: '2', key: '5678', name: 'John', picture: 'img/john.png' },
{ id: '3', key: '9012', name: 'Sarah', picture: 'img/sarah.png' },
{ id: '4', key: '0987', name: 'Tim', picture: 'img/tim.png' },
{ id: '5', key: '6543', name: 'Lily', picture: 'img/lily.png' }
];
usersResponseHandler(data);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Logged In User Key:
<div id="mySession">9012</div><br />
Name:
<div id="sName"></div>
Picture:
<div><img id="sImg" src="" /></div><br />
<button id="next">Next</button>

How to preselect items within a Fuel UX treeview?

so I've implemented the treeview of Fuel UX within my website. Whenever it's loaded, I need to reselect the items I want manually. Is there a possibility to preselect certain items after each reload?
Thanks in advance!
I was in the same situation since yesterday and could now solve the problem with the solution below. Just explaining that I used the methods present on the button "select nested Test Item 1" on this page. Here's the solution:
var preSelectFolder = function ($treeEl, folder, $parentEl) {
var $elParent = $parentEl || $treeEl;
if (folder.type == "folder") {
var $folderEl = $elParent.find("div.tree-folder-name").filter(function (_, treeFolder) {
return $(treeFolder).text() == folder.name;
}).parent();
$treeEl.one("loaded", function () {
$.each(folder.children, function (i, item) {
preSelectFolder($treeEl, item, $folderEl.parent());
});
});
$treeEl.tree("selectFolder", $folderEl);
}
else {
preSelectItem($treeEl, folder, $elParent);
}
};
var preSelectItem = function ($treeEl, item, $parentEl) {
var $elParent = $parentEl || $treeEl;
if (item.type == "item") {
var $itemEl = $elParent.find("div.tree-item-name").filter(function (_, treeItem) {
return $(treeItem).text() == item.name && !$(treeItem).parent().is(".tree-selected");
}).parent();
var itemId = $($itemEl).data() != null ? $($itemEl).data().id : "";
if (itemId == item.id)
$treeEl.tree("selectItem", $itemEl);
}
else if (item.type == "folder") {
preSelectFolder($treeEl, item, $elParent);
}
};
And in the event of 'loaded' I use this code:
element.on('loaded', function (e) {
angular.forEach(scope.items, function (item) {
preSelectItem($("#BuildTree"), item);
});
});
I use AngularJs so just replace "angular.forEach" for each function of Jquery and "scope.items" are items that should be pre-selected. In my case the items are in the following format:
[
{ name: 'Dir 1', type: 'folder', id: 'D1' },
{ name: 'Dir 2', type: 'folder', id: 'D2' },
{ name: 'Item 1', type: 'item', id: 'i1' },
{ name: 'Item 2', type: 'item', id: 'i2' }
]
Hope that helps.
If by manually, you mean you're actually clicking on the items again there should be a way to do this more programmatically.
I haven't tested it, but if you call $('#MyTree').tree('selectItem', $el) where $el is a .tree-item element, that should select the item.
It would be nice for your datasource to be able to tell the tree which items are selected. I see you've posted the feature request to https://fuelux.uservoice.com/forums/181290-general/suggestions/4097231-add-preselect-option-for-treeview which is great - anyone else reading this who agrees it would be useful should vote there.
I make if for ASP.NET MVC. I use a dynamic tree.
At first I received a route for selected item
[{
"id": 1, // parent category
"name": "Все категории",
}, {
"id": 56, // 1-st sub category
"name": "Для дома",
}, {
"id": 63, // item
"name": "Домашние растения",
}]
Then it need to switch off Async request for Ajax in dataSource function: 'async':false
This is all code:
#{
var jsonSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string catRoute = jsonSerializer.Serialize(ViewBag.catRoute);
}
var catRoute = $.parseJSON('#Html.Raw(catRoute)'); // this is object of item route
function dynamicDataSource(openedParentData, callback) {
var childNodesArray = [];
$.ajax({
'type': 'post',
'url': '#Url.Action("getFuelUxTree", "Category", new { area = "Root" })',
'data': openedParentData,
'async':false // switch off ajax request
})
.done(function (data) {
childNodesArray = data;
lastTree = data;
callback({
data: childNodesArray
});
});
}
$('#categoryTree').tree({
dataSource: dynamicDataSource,
multiSelect: false,
folderSelect: false
});
// iterate all route items and open category
for (var i = 0; i < catRoute.length; i++) {
$('li#'+catRoute[i].id+' button', '#categoryTree').click();
}

Categories