how to access js object properties? - javascript

I'm lost on how to get object properties in JS. I'm getting values from firebase and I wanted to filter the result by its id:
//id is from query params (selecting 1 item from view)
const snippet = snippets.filter(snips => {
if(snips.id == id) return snips;
})
If I console.log after these lines, I'm getting this:
const obj = snippet[0];
So I tried to get properties by using snippet[0] which returns this:
But if I try to get properties such as:
console.log(obj['id']);
//console.log(obj.title); - tried this as well
it returns:
Entering data:

This isn't how the array::filter function works. It iterates over the array and the callback returns a boolean true/false if the element should be returned in the result array.
const snippet = snippets.filter(snips => snips.id == id)
Issue
Cannot read property "title" of undefined
This is saying that snippet[0] is currently undefined when trying to access any properties
snippet[0].title, a root title property also doesn't exist in your other console log
Solution
Your snippet is (possibly) an array of 1 (or 0) element, so in order to access the title nested in data property
snippet[0].data.title
And in the case that the array is empty or has an element without a data property, use optional chaining or guard clauses to check the access
snippet[0]?.data?.title
or
snippet[0] && snippet[0].data && snippet[0].data.title

looking at what you are asking you need to enter first the data.
console.log(obj[0].data.content)

Related

Update and delete an object within an array of a Pinia store in Vue

I am making a CRUD in Vue 3 and I am using Pinia to save my objects as an array. Everything works fine but already when I want to update one of the objects I get the error of:
[Vue warn] Set operation on key "id" failed: target is readonly
[Vue warn] Set operation on key "length" failed: target is readonly
In my store I define my array as follows:
const companies = ref<Company[]>([])
In my composable since I have the object with the updated data stored in data.data and the id parameter which is an attribute of the object I try to do the following:
const { companies } = store
const index = companies.findIndex(c => c.id = id)
if(index > -1)
companies.splice(index, 1, data.data)
store.setCompanies(companies)
However, it is in the splice method that gives me this error, whether I want to use it to replace the object or to remove it from the array.
I have seen that there is a store.$patch method but I do not know if it applies to this case, and if I wanted to apply a filter and then replace the entire array in the long run that are many objects I don't see it convenient.

Lodash to check object property on array elements

I want to use lodash to find a property of an object at a specific array element.
Lets say I am hitting an api and getting response which sets it to the react state "personsDetails" (whose initial value was null), so now it becomes
let personsDetails=[{name:'king',id:2},{name:'queen',id:3}] //sometimes i get 1 object and sometimes 2
now when i want to access "name" property of 2nd object i do
personsDetails && personsDetails[1] && personsDetails[1].name
So is there any shorted syntax of accessing it via using lodash ? If the values doesnt exist i need null
As far as i know _get property works with object only so here i am dealing with array and then object
You can still use get and set the default as null
let personsDetails=[{name:'king',id:2},{name:'queen',id:3}]
let res = _.get(personsDetails, '1.name',null) //or _.get(personsDetails, '[1].name',null)
console.log(res)
console.log(_.get(undefined, '1.name',null))
console.log(_.get([], '1.name',null))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
or can use nth along with get and set the default as null
let personsDetails=[{name:'king',id:2},{name:'queen',id:3}]
let res = _.get(_.nth(personsDetails,1),'name',null)
console.log(res)
console.log(_.get(_.nth([],1),'name',null))
console.log(_.get(_.nth(undefined,1),'name',null))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

"undefined" before actual value in LocalStorage

This is the code I use:
localStorage["FSS"] += JSON.stringify(favSongs);
localStorage["FSTS"] += JSON.stringify(favSongTitle);
localStorage["FIS"] += JSON.stringify(favImages);
But when I retrieve the values I get this:
For FSS: undefined["0t0FGyhB6C8"]
For FSTS: undefined["SONIC SYNDICATE - Denied (OFFICIAL MUSIC VIDEO)"]
For FIS: undefined["https://i.ytimg.com/vi/0t0FGyhB6C8/mqdefault.jpg"]
I don’t understand how and where the undefined comes from and how I remove it to log the results on my screen (now when I log it it says undefined as well).
The undefined is what was already in localStorage:
document.getElementById('existing').textContent = localStorage[Math.random().toString()];
Because you use the foo += bar syntax, the script will:
Get the existing value of foo
Perform type coercion to make foo and bar compatible
Append bar to the existing value
Assign the combined value back to foo
If foo already contains undefined...
This appears to be an artifact of accessing the localStorage properties via the map accessor. If you used the getItem method, you would receive null instead of undefined.
Since you're working with JSON, the simple string concatenation (string +=) won't work even if you already have a value. You would end up with ['foo-album']['bar-album'], which is not valid. I would recommend getting the existing item or an empty array, appending your new item, then replacing the stored value:
var prev = localStorage.getItem('FSS') || '[]'; // get the existing value or the string representing an empty array
var data = JSON.parse(prev); // parse into an object
data.push('New Album');
localStorage.setItem('FSS', JSON.stringify(data)); // convert back to JSON and set

Adding a property to an Angular object

I am running an Angular app that pulls its data from a Web API service. The API returns the objects as JSON and the Angular service (via $http.get() ) returns them to the controller as an array of objects. Pretty normal stuff.
What I'd like to do is add a property to each of the returned objects called "Selected". This property is purely for GUI purposes (is the object selected or not in the UI) and doesn't need to be persisted in any way. I figured the easiest thing to do was loop through the returned array of objects and just add it. So my code looks like this:
function getData() {
myService.getData()
.then(function(data) {
$scope.myData = data.results;
// Add a "Selected" property to each object
$.each($scope.myData, function(item) {
item.Selected = false;
});
}
When it gets to the line that says, "item.Selected = false" it throw an error message, saying "Cannot assign to read-only property Selected".
It is unclear to me why "Selected" is read-only? I didn't know if maybe Angular does some funky object processing when it reads data? What am I doing wrong here? Or should I be approaching this a completely different way?
Note (I'd like to avoid having to make Selected a part of the original object, as it's not representative of anything related to that object).
to add property to an object use underscorejs,
"each _.each(list, iteratee, [context]) Alias: forEach
Iterates over a list of elements, yielding each in turn to an iteratee function. The iteratee is bound to the context object, if one is passed. Each invocation of iteratee is called with three arguments: (element, index, list). If list is a JavaScript object, iteratee's arguments will be (value, key, list). Returns the list for chaining."
"extend _.extend(destination, *sources)
Copy all of the properties in the source objects over to the destination object, and return the destination object. It's in-order, so the last source will override properties of the same name in previous arguments."
$scope.myData = data.results;
// Add a "Selected" property to each object
_.each($scope.myData, function(ent) {
_.extend(ent, {
Selected : false
});
});
Your debugger screenshot actually gives you a more useful error message than what you posted (emphasis mine):
Cannot assign to read only property 'Selected' of 0
This shows that instead of the object, you're getting a number as your item variable (0 in this case). Assigning properties to primitives in strict mode throws this "Cannot assign to read-only property" error. (Without strict mode, it just fails silently.)
As JcT pointed out in a comment, this is because $.each calls the function with 2 params passed, the index first, the value second. See the documentation of $.each:
callback
Type: Function( Integer indexInArray, Object value )
So even though you named your parameter item, it received the value of the current index instead. This means your code can be fixed by just adding this missing first parameter to your callback, like this:
function getData() {
myService.getData()
.then(function(data) {
$scope.myData = data.results;
// Add a "Selected" property to each object
$.each($scope.myData, function(index, item) { //index was added here!
item.Selected = false;
});
}

Get object property value

I have an object that contains an array of objects from which I need to get a value of their properties.
As an example this is what I need to get:
Stronghold.bins.models[0].attributes.entity.title
Which returns "Stronghold Title 1"
function grabItemName(){
var itemName=$(Stronghold.bins).each(function(){
return this.models[0].attributes.entity.title == title;
console.log(itemName);
})
};
(if there is a better way for me to ask this question please let me know)
I apologize if this was poorly asked!
The current issue is that it does not understand the array value '[0]' and cannot read it as it is undefined. What do I need to do to grab the 'title' value of all items in the array?
What do I need to do to grab the 'title' value of all items in the array?
That's what .map [docs] is for. It lets you map each value in an array to another value.
In the following I assume you want to iterate over each Stronghold.bins.models, because iterating over Stronghold.bins does not make sense with the provided information:
var titles = $.map(Stronghold.bins.models, function(obj) {
return obj.attributes.entity.title;
});
// `titles` is now an array containing `.attributes.entity.title;` of
// each object.
The current issue is that it does not understand the array value '[0]' and cannot read it as it is undefined.
Well, that won't happend anymore ;) In your example you where iterating over the properties of the Stronghold.bins object. One of these properties is models itself (!) and I doubt that any other property value has a models property.
Try using the other version of the each function:
$.each(Stronghold.bins, function () {
});
The version you are using is for looping through an element on the page, e.g $('body div p').each(function() {}), which isn't what you want in this instance: You want to loop over the values contained in Stronghold.bins.

Categories