Is it possible to assign new id to jstree nodes copied? - drag-and-drop

I have two jstree and dnd nodes from one to another using copy_node api. But copied nodes don't have original ids (json data ids). Auto generated ids assign them like 'j2_1'. I have original ids and want to change them with original ids. How can I implement this?

I know, it's been a while since you posted this question. However, I am working right now with jstree and had almost the same "problem".
I used data.original.id to get the original id of my copied item.
And I changed the id using $("#jstree").jstree(true).set_id(data.node,new_id);. In my case, I wanted my new id to involve the original one.
Here is my code block:
// this function is called, if I copy and paste a node
$("#jstree").bind('copy_node.jstree', function (e, data) {
var old_id= data.original.id;
// I just made a new id out of the old one, e.g. appending a number
var new_id = old_id+"1";
$("#jstree").jstree(true).set_id(data.node,new_id);

Related

Deleting parent node with child value

I am struggling to overcome to issue I have. I am trying to delete a parent node/key given I find the correct child value.
My database is structure liked this
I am querying my database by a certain value, objectID, as it will match the postID which is passed through the parameters. The objectID value is removed. However, I am struggling to remove the key in which it falls under.
I have had mixed results so far:
I can either remove the objectID value using this code:
refSnap?.ref.child("objectID").child(postID).removeValue()
Of I can remove the whole notifications node/directory, using this:
refSnap?.ref.child("objectID").queryEqual(toValue: postID).ref.removeValue()
refSnap?.key gives me all the keys/nodes under the notifications node.
I cannot access the key which the objectID and all other information is stored under as it is .childByAutoId. Can anyone possibly help me as to how I can sort this issue?
While the other answer provides some insight with an alternate and workable structure, the ability to delete a node based on a child is fairly straightforward and directly addresses the question without changing the structure.
(note that the structure may need to be changed anyway but for this exercise, we'll use it as is.)
Given a structure suggested in the question:
notification
"rtupy..." //childByAutoId
"-LFEMjAcny..." // childByAutoId
"-LFEzrrq..." // childByAutoId
from: "aw,sdasdad"
objectID: "-LFEMjAcn...."
timestamp: 15292
type: "comment"
Suppose you want to delete the node "-LFEzrrq..." as shown in your screenshot. That node contains the child objectID: "-LFEMjAcn...."
To delete the node you need query for the node that contains the objectID you want which, according to the question, is working and returning the correct child.
Use the returned snapshot to obtain it's parent key, and get the path to that node and delete it. Note that we don't know what process or code the OP used to obtain the node they want to delete - perhaps it was from another query and the node reference was passed in or some other means.
let queryRef = //unknown how, but build the query for objectID = "-LFEMjAcny...."
queryRef.observeSingleEvent(of: .value, with: { snapshot in
let key = snapshot.key //this is the parent key of the objectID node i.e. -LFEMzrrq..."
let parentRef = snapshot.ref.parent! //this is the path to that parent
let refToDelete = parentRef.child(key) //add the parent key to the path: -LFEzrrq
refToDelete.removeValue() //delete it
})
As you can see, regardless of the parent nodes' key, or how deep it is, this code will delete the node found in the query.
The key names do not matter so using .childByAutoId as references to tie your nodes together is safe and generally best practice as disassociating node keys from the data they contain makes your structure highly expandable.
Your issue is that you are using childByAutoId and you can't "tie" these random alphanumerics to something(in this case the post).
The structure that i would set is this:
-notifications
--uid //notifications for user
--- userAid+userBid //follow notification, if they unfollow you already now which one it is and you can go and delete it
---commentNotificationID // you give this notification the same Id that the comment has, so if the user deletes the comment you use that id to delete the notification as well.

Using childByAutoId On Single Value?

I am pretty new to both Swift and Firebase, and I am attempting to make a simple app using Firebase as the backend. As far as I know, there is no memory-efficient way to use the numChildren() function without loading every single child into memory for counting, so I am implementing my own simple counter for the number of "Events" that have been created in my app.
The documentation for Firebase states that the childByAutoID() method should be used for updating lists in multi-user applications. I am assuming it adds a timestamp to the requested update and does them in order.
My question is whether it is necessary to use childByAutoID() when only updating a SINGLE field in a multi-user application. That is, will there be conflicts on my numEvents field if I do:
dbRef = FIRDatabase.database().reference()
dbRef.child("numEvents").setValue(num)
Or must I do:
dbRef = FIRDatabase.database().reference()
dbRef.child("numEvents").childByAutoId().setValue(num)
In order to avoid write conflicts? My only real confusion is that the documentation for childByAutoID stresses that it is useful when the children are a list of items, but mine is only a single item.
If you are only updating a single field you should not be using childByAutoId. To update a child value for an object, you need to obtain a reference to that object somehow, perhaps by a query of some sort (in many cases you will naturally already have a reference to the object if it needs to be changed) and you can change the value like this:
dbRef.child("events").child(objectToUpdateId).child(fieldToUpdateKey).setValue(newValue)
childByAutoId in this context would be used to create a new field like:
dbRef.child("events").childByAutoId().setValue(newObject)
I'm not exactly sure how this applies to your situation, but those are some descriptions of how to update a field, and use childByAutoId.
What childByAutoId does is create a unique key for a node, to avoid using the same key multiple times and then creating data conflicts like inconsistency (not write conflicts) to avoid write conflicts you use the transaction blocks.
The best way to learn is to try it out
If num == 1 , in the first example the result will be
dbRef:{
numEvents:1
}
While the second will be
dbRef:{
numEvents:{
//The auto-generated key
KLBHJBjhbjJBJHB:1
}
}
The childByAutoId would be useful if you want to save in a node multiple children of the same type, that way each children will have its own unique identifier
For example
pet:{
KJHBJJHB:{
name:fluffy,
owner:John Smith,
},
KhBHJBJjJ:{
name:fluffy,
owner:Jane Foster,
}
}
This way you have a unique identifier for cases where there is no clear way with the item data to guarantee it will be unique (in this case the pet's name)
Few things here:
childByAutoId is not a timestamp. But is used to create unique nodes in any given node.
Use case of childByAutoId :
You have messages node which stores messages from multiple user who are involved in a group chat. So each user can add messages in the group chat so you would do something like this each time user sends message:
dbRef = FIRDatabase.database().reference()
dbRef.child("messages").childByAutoId().setValue(messageText)
So this will create a unique message id for each message from different users. This will kind of act like primary key of message in normal databases.
The structure of database will be something like this:
messages: {
"randomIdGenerated-12asd12" : "hello",
"randomIdGenerated-12323D123" : "Hi, HOw are you",
}
So in your case your first approach is good enough! Since you dont need unique node for counting number of events added.

How to save one value of Parse object without overwriting entire object?

I have two users accessing the same object. If userA saves without first fetching the object to refresh their version, data that userB has already successfully saved would be overwritten. Is there any way(perhaps cloud code?) to access and update one, and only one, data value of a PFObject?
I was thinking about pushing the save out to the cloud, refreshing the object once it gets there, updating the value in the cloud, and then saving it back. However that's a pain and still not without it's faults.
This seems easy enough, but to me was more difficult than it should have been. Intuitively, you should be able to filter out the fields you don't want in beforeSave. Indeed, this was the advice given in several posts on Parse.com. In my experience though, it would actually treat the filtering as deletions.
My goal was a bit different - I was trying to filter out a few fields and not only save a few fields, but translating to your context, you could try querying the existing matching record, and override the new object. You can't abort via response.failure(), and I don't know what would happen if you immediately save the existing record with the field of interest and null out the request.object property - you could experiment on your own with that:
Parse.Cloud.beforeSave("Foo", function(request, response) {
// check for master key if client is not end user etc (and option you may not need)
if (!request.master) {
var query = new Parse.Query("Foo");
query.get(request.object.id).then(function(existing) {
exiting.set("some_field", request.object.get("some_field"));
request.object = exiting; // haven't tried this, otherwise, set all fields from existing to new
response.success();
}, function(error) {
response.success();
});
}
});

Firebase: how to generate a unique numeric ID for key?

I need numeric IDs for human readability. How do I get it in Firebase?
I want numeric ID for keys, e.g. "000000001", "000000002","00000003","00000004".
The reason I need it is because these IDs will become the permanent object ID both online and offline. I want users to be able to browse that object page by just entering URL "/objects/00000001" without efforts.
I am asking here, because I want to know if this can be done without using .priority, sub-properties, etc. I guess set method can do it somehow. If it is not possible, just tell me no, I can accept that answer.
I'd suggest reading through the Firebase documentation. Specifically, see the Saving Data portion of the Firebase JavaScript Web Guide.
From the guide:
Getting the Unique ID Generated by push()
Calling push() will return a reference to the new data path, which you can use to get the value of its ID or set data to it. The following code will result in the same data as the above example, but now we'll have access to the unique push ID that was generated
// Generate a reference to a new location and add some data using push()
var newPostRef = postsRef.push({
author: "gracehop",
title: "Announcing COBOL, a New Programming Language"
});
// Get the unique ID generated by push() by accessing its key
var postID = newPostRef.key;
Source: https://firebase.google.com/docs/database/admin/save-data#section-ways-to-save
A push generates a new data path, with a server timestamp as its key. These keys look like -JiGh_31GA20JabpZBfa, so not numeric.
If you wanted to make a numeric only ID, you would make that a parameter of the object to avoid overwriting the generated key.
The keys (the paths of the new data) are guaranteed to be unique, so there's no point in overwriting them with a numeric key.
You can instead set the numeric ID as a child of the object.
You can then query objects by that ID child using Firebase Queries.
From the guide:
In JavaScript, the pattern of calling push() and then immediately calling set() is so common that we let you combine them by just passing the data to be set directly to push() as follows. Both of the following write operations will result in the same data being saved to Firebase:
// These two methods are equivalent:
postsRef.push().set({
author: "gracehop",
title: "Announcing COBOL, a New Programming Language"
});
postsRef.push({
author: "gracehop",
title: "Announcing COBOL, a New Programming Language"
});
Source: https://firebase.google.com/docs/database/admin/save-data#getting-the-unique-key-generated-by-push
As explained above, you can use the Firebase default push id.
If you want something numeric you can do something based on the timestamp to avoid collisions
f.e. something based on date,hour,second,ms, and some random int at the end
01612061353136799031
Which translates to:
016-12-06 13:53:13:679 9031
It all depends on the precision you need (social security numbers do the same with some random characters at the end of the date). Like how many transactions will be expected during the day, hour or second. You may want to lower precision to favor ease of typing.
You can also do a transaction that increments the number id, and on success you will have a unique consecutive number for that user. These can be done on the client or server side.
(https://firebase.google.com/docs/database/android/read-and-write)
Adding to the #htafoya answer.
The code snippet will be
const getTimeEpoch = () => {
return new Date().getTime().toString();
}
As the docs say, this can be achieved just by using set instead if push.
As the docs say, it is not recommended (due to possible overwrite by other user at the "same" time).
But in some cases it's helpful to have control over the feed's content including keys.
As an example of webapp in js, 193 being your id generated elsewhere, simply:
firebase.initializeApp(firebaseConfig);
var data={
"name":"Prague"
};
firebase.database().ref().child('areas').child("193").set(data);
This will overwrite any area labeled 193 or create one if it's not existing yet.
https://firebase.google.com/docs/firestore/manage-data/transactions
Use transactions and keep a number in the database somewhere that you can increase by one. This way you can get a nice numeric and simple id.

How to programmatically refresh a screen from onFinished callback function?

e.g. we have this one guy calling server function for creating a new entity:
function loadData() {
var vServerController = mobileController.serverController();
var vJSONRequest = vServerController.createJSONRPCRequest();
vJSONRequest.setQueryMethod("createSomeNewElementBasedOnTwoIds");
vJSONRequest.addParameter("firstID", 1);
vJSONRequest.addParameter("secondID", 2);
vJSONRequest.setOnFinish(callBackOnFinish);
vServerController.addToQueue(vJSONRequest);
}
function callBackOnFinish() {
var vController = mobileController.activeController();
vController.showView(Screens.SomeScreen, true);
}
So how we can refresh a Screen after this call? The server will return not a full set of data but just a new one.
What is the best approach to doing this?
Assuming you want to update the currently displayed data, you have two options - and you propably don't need to use a callback for this
Replace the displayed dataset
Update the displayed record
(if you had user input or created a new entry) merge the entries
1: just return the data from the server with foundset.setDataMode(DataMode.REPLACE) - it will automatically refresh the displayed data. But In case you are working with multiple records for one entity and you only want to update one of them, use option 2.
2: Return only the specific record you want to update without datamode replace. The record is identified by it's key/id elements. You can find those marked with a little key symbol in the entity editor. So just make sure that those key elments and any additionaly elements you want are returned. The AppConKit will automatically merge the existing record with the data and display that.
3: If you created a new record on the device, that record will have a value called client_uuid. If you now return a record from the server that contains both the client_uuid AND the key element, the record created on the device will be merged with the server created record and the new record will displayed
Hope this helps!