Update Firebase with dynamic state properties - javascript

I have a Firebase database structure like this:
-KrVtLbX7w8LKHC888cx
siteInfo
description: "Udemy is an online learning and teaching market..."
siteName: "Udemy"
title: "Udemy Online Courses - Learn Anything, On Your ..."
type: "video_lecture"
url: "https://www.udemy.com/"
Each of these siteInfo nodes could potentially contain different keys (ie. one might not have a type and another could have an img). This makes the data keys relatively dynamic so I can't explicitly set them in firebase.update.
On the frontend, I have a form for the user to edit the site information. The form displays the data in individual input fields for the user to edit depending on which site the user has selected and this is working great.
My problem is submitting an update to the data node that the user is updated.
Right now I'm setting the state for the inputs that have changes like this:
handleChange = ({target}) => {
this.setState({
[target.name]: target.value
});
}
And updating the node like this:
firebase.database().ref().child(`paths/${this.props.uid}/${key}`);
let siteInfo = this.state;
firebaseRef.update({
siteInfo
});
What this is doing is deleting the entire siteInfo node and adding only those fields that the user has edited. So instead of getting this where only the description has been updated:
-KrVtLbX7w8LKHC888cx
siteInfo
description: "The updated description!"
siteName: "Udemy"
title: "Udemy Online Courses - Learn Anything, On Your ..."
type: "video_lecture"
url: "https://www.udemy.com/"
I'm getting this where it's updating the edits made by the user but everything else is deleted:
-KrVtLbX7w8LKHC888cx
siteInfo
description: "The updated description!"
siteName: "The updated site name!"
I want it to only update those keys that have been updated though. This is my understanding of how the .update method for Firebase is supposed to work but for some reason it's just overwriting everything here.

This was actually a pretty silly oversite on my part. State is already submitting the data as an object so instead of doing this (with the extra object wrapper):
firebaseRef.update({
siteInfo
});
I should have just done this:
firebaseRef.update(siteInfo);

Related

How do i connect MongoDb models

I am using MERN stack. I have 3 models created for my database user, subject and comment. Subject and comment both have author properties set to type mongoose.ObjectId but this only saves the id and not the full object. What should i change it to so that all the user information shows?
author: {
type: mongoose.ObjectId,
},
but this only saves the id and not the full object
that's the intended behaviour when using refrences. saving the refrence id, but allowing to access the full object by that id.
What should i change it to so that all the user information shows?
By using populate, you can expand your result to replace the id by whole object, when you access it.
Subject.find({}).populate('author').then(subjects => {
// now subjects[0].author is the whole object of author.
})
learn more about populate here

Setting up Segment.io

I have recently finished building a website on Webflow and I am looking to integrate Segment.io onto my website to connect with different destinations. I haven't been able to figure out how I could go onto collecting event and identity data into segment.io.
I have gone on their website and have seen example scripts (as shown below) but, I can seem to figure out anywhere how I could replace the dummy from the hard-coded strings to be functional on my HTML coded website.
analytics.identify('f4ca124298', {
name: 'Michael Bolton',
email: 'mbolton#initech.com'
});
analytics.track('Article Bookmarked', {
title: 'Snow Fall',
subtitle: 'The Avalanche at Tunnel Creek',
author: 'John Branch'
});
Is there anyone that has been successful in setting up Segment.io on their projects?
this code snippet goes on your web page, usually in a javascript import. Depending on how you are setting up your page, but simple javascript would be populating using the DOM values..
The first example, using an identify call, typically happens on a form submit.
var name = document.getElementById('name_field').value;
var email = document.getElementById('email_field').value;
var user_id = document.getElementById('user_id_field').value;
analytics.identify(user_id, {name: name, email: email});
Similar thinking when using the track calls..

Liferay 7: Retrieved custom field value using javascript api jsonws return java.lang.NullPointerException

I'm very new to liferay, I've created a page custom field using 'control panel > configuration > custom fields > page'. My goal is to retrieve the value from the page custom field and display the value in my custom portlet. One of the methods I've tried is using ExpandoValue/get-data API from the liferay json web service and this API is generated from localhost:8080/api/jsonws. Below is the generated javascript API:
Liferay.Service(
'/expandovalue/get-data',
{
companyId: themeDisplay.getCompanyId(),
className: 'com.liferay.portal.model.Page',
tableName: 'CUSTOM_FIELDS',
columnNames: 'pageDetail',
classPK: themeDisplay.getUserId()
},
function(obj) {
console.log(obj);
}
);
However, this api throws me an error: java.lang.NullPointerException. I'm thinking that this error occurs due to the permission given to the custom field. So, I've ticked View and Update permissions for Guest. But the issue persists.
My question is what triggered this error and how to fix it and is there any other solution I can use to retrieve the value from the page custom field?
Thanks in advance.
Edit
I had misunderstanding in assigning the attributes for the api and here is the new api as suggested by Olaf.
Liferay.Service(
'/expandovalue/get-data',
{
companyId: 20115,
className: 'com.liferay.portal.kernel.model.Layout',
tableName: 'CUSTOM_FIELDS',
columnName: 'details',
classPK: themeDisplay.getLayoutId()
},
function(obj) {
console.log(obj);
}
);
It works fine. However it only took the default value but not the value assign for that particular pages.
If memory serves me right, the stock remote API can't be used by unauthenticated users, but requires at least a logged in user (on top of the regular permissions of course).
You can test for this by accessing the API from logged in accounts with the same permissions. If it works there, then this is what you're running into.
However, when I interpret the call in your question correctly, the current user id would be the primary key for the custom field that you're looking at (looking at your classPK value). For a custom field on the page, I'd have expected a page id (layoutId in Liferay-API-terms). And while I'm seeing this, I notice com.liferay.portal.model.Page in your snippet. I've not seen that class, and pages can rather be found in com.liferay.portal.kernel.model.Layout (Assuming Liferay 7.1)
This makes me wonder what you're trying to achieve here - are you rather looking for a user-specific field (that would then be a custom field on the user) or really a page-specific field? Anyways - as this is an answer, not a comment, it might give enough hints to try out and come closer to a solution.

Firebase link data to user

How do I link the data to the user?
In my case I have a comments section on my blog, where the user can post a comment.
The structure looks something like this:
- posts
- My First Post
- content: "a big string of the post content"
- data: "Date Created"
- image: "Image URL"
- imagecaption: "Image Caption"
- comments
- ???
Now under the comments it would be nice to have something like this:
- comments
- HbsfJSFJJSF (Comment ID)
- user: (User Reference)
- comment: "Nice Blog!"
Now I understand I could so something like this:
- comments
- HbsfJSFJJSF (Comment ID)
- user: user_uid
- comment: "Nice Blog!"
But that has the problem(?) that if the account is deleted (I have that feature), the comment won't be deleted.
Is there a proper way to link the data (comment) to the user such that when the users account is deleted the comment gets deleted, or at least is there a way to delete the comments corresponding to the user when his/her account is deleted?
Your idea of using user: user_uid under each comment node would work and is known as denormalisation and fanout.
Using this method, you could cascade deletes by performing a query to obtain all comments where the user value is equal to the current user's ID, and delete each one, something like:
var commentsRef = firebase.database().ref('comments');
var userId = firebase.auth().currentUser.uid;
commentsRef.orderByChild('user').equalTo(userId).once('value', function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var commentKey = childSnapshot.key;
commentsRef.child(commentKey).remove();
});
});
To ensure this is performed behind the scenes when a user is deleted, you could move the above logic into a Cloud Function that's triggered by a delete request.
There is no built-in support in the Firebase Realtime Database for a managed link. So it's up to code that you write.
Frequently this means that you'll have a central function (possibly in Cloud Functions for Firebase) that handles the deletion of a user. This function then calls Firebase Authentication to delete the user, and it updates the database to remove the references to the user.
There is also an open-source project that aims to make this sort of clean-up operation simpler/more reliable: https://github.com/firebase/user-data-protection

Create new item in Firebase using form

I am building a web app for a party planning iOS app and I want to have a form where users can create new events through a web form that is submitted using that data.(Sounds better in my head :/ )
In our database there is a tree called "events" where all the events and their details are stored. As an example let's say that I want a form to post the name of the event and the date of the event then have it be stored under the event tree.
After looking at the firebase documentation for a while it seemed like using the update/add user snippet could be the framework for this project.
user.updateProfile({
displayName: "Jane Q. User",
photoURL: "https://example.com/jane-q-user/profile.jpg"
}).then(function() {
// Update successful.
}, function(error) {
// An error happened.
});
But instead of using "Jane Q. User" I would want to call a form field and its data. Am I going about this the right direction or am I up the wrong tree?

Categories