_.keys not finding every Item shown in Firebug - javascript

I have a post, saved to $scope.mydata in the controller. I give this data via a parameter to a service that returns a function.
The service:
module.factory('myservice', function () {
return function servicefunction(mydata) {
var test = _.keys(mydata).length;
console.log("mydata", mydata);
console.log("test", test);
Firebug in Firefox shows me in the dom that mydata contains:
Object { $$state={...}, angularCollection=false, $object={...}, mehr...}
and the test returns 5.
When I type
module.factory('myservice', function () {
return function servicefunction(mydata) {
var test = _.keys(mydata.$$state).length;
console.log("mydata", mydata.$$state);
console.log("test", test);
Firebug gives me the Object { status=0} and in the DOM there is status and value []. I need to get access to that value. The test returns 1 for the status.
Why test via _.keys finding the status but not the value?

It looks like you are trying to access a property (value) that is inherited from your mydata.$$state's prototype. In that case, using _.keys will never list value.
It may very well be that it is inherited for now because it is empty, and it will become an own property once it is set.
Why not simply accessing it like so: mydata.$$state.value? It should work for both cases (inherited and owned).
I may lack a major part of your context, so if it still does not work, it would be worth providing more information about your data.

Related

Computed property get returned twice

I want to get the initials of the full name using computed properties but it returns undefined and tries to get the initials before it renders the full name as shown below
computed: {
user: function () {
console.log(this.$store.state.user.name);
//return this.$store.state.username.match(/[A-Z]/g).slice(0, 2).join('');
}
}
How to get this to work? like it doesn't call match function unless the full name is rendered?
The way the computed property is running twice, is once when the app is created, then once your data updates, running twice.
Best way to handle this is wherever your data is to change the computed property to check if the data is there, like so:
if(this.$store.state.user.name) return this.$store.state.user.name
Or if you are placing your computed property to the template, use a v-if:
v-if="$store.state.user.name"
You can use Optional Chaining to handle undefined cases within your return statement.
MDN
computed: {
user: function () {
return this.$store.state?.user?.name?.match(/[A-Z]/g).slice(0, 2).join('');
}
}

Angular Http subscribe - cannot assign to variable in component

I want to retrieve data from api and assign it to some value inside the angular component. In subscribe I'm trying to assign the data to loggedUser and then call function inside this subscribe to navigate to another component with this received object. Unfortunately I got the error : The requested path contains undefined segment at index 1. I want to have this object set outside the subscribe too. How can I achieve this?
logIn() {
this.portfolioAppService.logIn(this.loggingUser).subscribe((data) => {
this.loggedUser = data;
console.log(this.loggedUser);
console.log(data);
this.navigateToProfile(this.loggedUser.Id);
});
}
navigateToProfile(id: number) {
this.router.navigate(['/profile', id]);
}
console output
You are using an incorrectly named property when calling navigateToProfile.
From your console output, I can see that the data object in the subscribe looks like this:
{
id: 35,
// ..
}
But you are calling the function like this:
this.navigateToProfile(this.loggedUser.Id);
Instead, use the property id (lower case)
this.navigateToProfile(this.loggedUser.id);
To narrow this problem down in the future, try being more specific in your testing. Humans are good at seeing what they want to see and will assume the problem is more complicated than it is. If you had tried console.log(this.loggedUser.Id), you would have seen the result undefined, and worked out the problem yourself.

If the same value is being printed on the console before calling axios, why is it that a different value gets sent to the server?

I have a form field that has the following generic autocomplete:
<generic-autocomplete
v-model='c.heuristicId'
v-on:change='heuristicSelected(i, $event)'
label='Fuente de datos'
:apiFunction='heuristicsFetchFunction'
:disabled='disabled'/>
When saving the form and sending it with this field in blank heuristicIdgets sent as nullwhich is what is desired.
However, when selecting a value from the generic autocomplete and then deleting it, heuristicIdgets sent with the id of the previously selected value.
Inside the function that calls axios I'm logging console.log("heuristicId to be sent: " + campaign.heuristicId);and undefinedgets logged in both scenarios.
EDIT: After inquiring a little bit more I believe that the error might be in one of <generic-autocomplete/>'s computed properties:
isValid: function () {
// this checks that the name in display equals the object selected in
// memory so no invalid labels are displayed while a valid object is 'selected'
let vc = this
let result = false
if (vc.object) {
result = vc.objectName === vc.object.name
console.log('generic-autocomplete#isValid', result)
}
return result
}
An empty vc.objectwill return a falseresult and I haven't been able to satisfactorily handle that.
After logging a really complex control flow I finally got to the point where I knew which properties I had to mutate. However, it turns out that in Vue 2 mutating inline properties is an anti-pattern. The capability of mutating inline props was deprecated from the previous Vue version in order to be consistent with the library's fully reactive paradigm. So what happens is that if you try to mutate an inline property, when the component re-renders, such property will be set back to its default (or previous) value.
This is solved by adding a computed property that's a copy from the property that you want to mutate.
//Somewhere else in the code the property is defined
property: null
//Add the computed property
data: function () {
return {
mutableProperty: this.property,
}
}

Hidden properties to console.log or utils.inspect

I'm working with sails.js waterline orm. Now this is not particularly a sails question, but i have to place some context, so when you create a record you get back an object with the data created. If the record has other records (collections) associated, it has keys related to those in the returned object, but those keys are getters/setters, even if no data is present for those related objects.
I've simplified a few things just to expose the main point.
This is my user model:
var User = {
attributes:
status: {type:'string'}
images: {
collection: 'Image'
}
}
Lets assumme, i performed a create query on a User model, that has a images collection associated. The userRecord is what the query returned.
if i console.log this out it shows the properties related to the model itself
but not the associated records, even though the key is actually there, you can
access it but is not visible to console.log or utils.inspec even when setting show hidden to true.
console.log(userRecord)
This is what gets returned
{ name: 'zaggen'}
This is what should get returned
{ name: 'zaggen',
images: [{
path: 'some-path/img.png'
}]
}
And i can access the hidden property like this:
console.log(userRecord.images[0].path)
// outputs some-path/img.png
How is this even possible?, as far as i know there is no way to hide info to the console.log in node, except maybe when the properties are defined in the __proto__ object, but in this case they are not.
After searching for this i haven't found anything and its pretty weird so i thought it could be a good question for SO. It'll help on my work process if i could console.log this info and get all the data, right now i can use lodash and call clone or defaults and i get the object as it should.
as far as i know there is no way to hide info to the console.log in node, except maybe when the properties are defined in the proto object
That's no longer true in ES5. It was true in ES3.
Notice that even in the original javascript, objects and functions have hidden properties like .__proto__ or .constructor or .prototype? It was like some native javascript objects have these magic features (like how setting innerHTML can call the HTML compiler). ES5 exposes all that magic by way of Object.defineproperty.
The specific feature that hides a property from console.log() is enumerable. Setting it to false on a property makes it hidden from for..in (no need for .hasOwnProperty() anymore):
var foo = {a:1}
Object.defineProperty(foo,'b',{
enumerable: false, // hide it from for..in
value: 2
})
console.log(foo); // prints out {a:1}
console.log(foo.b); // prints out 2
There are other useful features such as getters and setters (allowing you to emulate properties like .innerHTML that calls a function when you write to it) and writable (allowing you to make a property read-only). See the full documentation for details: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Sails uses waterline which is where the model is defined. If you take a look at the source code for it, you see this:
https://github.com/balderdashy/waterline/blob/77fe3a9b9a9b12110a6ba079a84e5cd43a4369db/lib/waterline/model/lib/model.js#L57-L75
/**
* Log output
* #return {String} output when this model is util.inspect()ed
* (usually with console.log())
*/
Object.defineProperty(this, 'inspect', {
enumerable: false,
configurable: false,
writable: false,
value: function() {
var output;
try {
output = self.toObject();
} catch (e) {}
return output ? util.inspect(output) : self;
}
});
So they override the console.log output to self.toObject(). This is one of their internal methods that does all kinds of stuff that could be responsible for the output your seeing. For example:
// Don't run toJSON on records that were not populated
if (!self.proto._properties || !self.proto._properties.joins) return;
Or:
if (!this.proto._properties.showJoins) return;
I noticed in their integration tests, they pass { showJoins: true } as the second argument when creating the model. I couldn't find anything about it in the docs, but maybe you could try that?
https://github.com/balderdashy/waterline/blob/48dc007b69a133169651aeb422fa3a61c3c6802c/test/integration/model/save.js#L150

Best way of getting the key after $add

I am using angularFire v 0.5.0
On my returned object I do a $add.
What would be the best way to get the generated key?
It must be something in the succes callback of the $add, because the key will come back asynchrounlusly?
scope.settings = $firebase(ref);
scope.settings.value = {
vat: {
inclusive: true
}
}
}
scope.settings.$add (scope.settings.value).then( function ( {
scope.settings.key = ???
});
note: this is not the actual code, this is just to clarify the problem.
The actiual code is inside a factory in the loaded event, and there is a check if there is already a settings object inside the database.
This somewhat strange construct is to make it easyer for consumers of the factory to change the settings. The settings is a singleton. AngularFire does not return a array of objects, but every item is a object in the settings, with its own key.
$add returns a Firebase ref. Call name() on that ref.
scope.settings.$add(…).name();
See https://github.com/firebase/angularFire/blob/master/angularfire.js#L127.
from the angularfire docs:
The $add method takes a single argument of any type. It will append this value as a member of a list (ordered in chronological order). This is the equivalent of calling push(value) on a Firebase reference.
from the firebase docs (about push()):
Returns
A Firebase reference for the generated location.
so, i think the "key" that you want is the return value of the $add.
Maybe they've changed it in newer versions, now it works like this:
$add() will return a promise. You have to use the callback which runs on success. For example:
var something = $scope.somethings.$add({name: "foo"});
something.then(function(e) {
console.log(e.name())
});
This allows you to perform different actions based on the outcome of the save/write attempt to Firebase.

Categories