Hello I am learning angular and I'm working on a todo app that stores to local storage. Getting the local storage to remove a single item as well as editing an item has been a challenge and I've not found many good resources.
Right now it looks like its removing the entire array and I'm not sure why. Hopefully Ive included the proper details.
This is is my delete/remove in the CRUD task
deleteTask(task : Task) {
localStorage.removeItem(this.taskKey)
}
This is the delete task in the componant
deleteTask(idx: number) {
this.taskService.deleteTask(new Task(this.addTaskValue))
if( idx >= 0) {
this.taskArr.splice(idx, 1);
}
}
Other Details from the componant
taskArr: Task[];
public addTaskValue: string = '';
constructor(private taskService: TaskService) {}
ngOnInit(): void {
this.addTaskValue = '';
this.taskArr = this.taskService.getAllTasks();
}
Local Storage Image
I've tried to just use the splice out in the deleteTask but that only removed it from the screen and not the local storage. Ive tried a bunch of other things as well but cant recall them all in detail.
In the above code, you provided. I don't see a logic where the taskKey is even being set. I would add some console statements to see if you're even getting the right string in this.taskKey.
deleteTask(task : Task) {
console.log(this.taskKey); // check if this value is "tasks"
localStorage.removeItem(this.taskKey)
}
Essentially it needs to boil down to this.
localstorage.removeItem('tasks').
Related
Suppose you have 150 images stored in the images folder within your Firebase Storage. Each image should have a title, which will be inserted during the uploading process. Now, let's say you want to display all of these images in a RecyclerView. In this scenario, you would need to create 151 separate connections to the server instead of just one. This may seem counterintuitive, so allow me to explain.
The first connection is to retrieve all the images using the following line of code: FirebaseStorage.getInstance().getReference().child("Images/").listAll(). This will return a list of all the images in the folder.
For each image, you would need to make another connection to the server to retrieve the metadata for that image. This means that for every single image, you would need to make a separate call to the server, resulting in a total of 151 connections.
Here is a preview of the code for this scenario:
FirebaseStorage.getInstance().getReference().child("Images/").listAll().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
for (int i = 0; i < 150; i++) {
task.getResult().getItems().get(0).getMetadata().addOnCompleteListener(task1 -> {
if (task1.isSuccessful()) {
task1.getResult().getCustomMetadata("title"); //Finally I got the image title that stored inside image, it is cumbersome process.
} else {
//Handle error
}
});
}
} else {
//Handle error
}
});
However, it's possible that I may be missing something. Is this really the way it works, or is there a better solution? I don't want to name the image directly as the file name because I've tried that before and found that the length is not enough.
I would greatly appreciate any suggestions or alternative solutions to this problem. Thank you in advance!
Additionally, I would like to express my gratitude to OpenAI's GPT-3 for helping me write this clear and concise question.
First of all, FirebaseStorage.getInstance() is a singleton, which will always create a single instance.
Furthermore, while Mauricio Gracia Gutierrez's will work, please see below a solution that uses Tasks#whenAllSuccess(Collection> tasks):
StorageReference imagesRef = FirebaseStorage.getInstance().getReference().child("Images/");
imagesRef.listAll().addOnCompleteListener(new OnCompleteListener<ListResult>() {
#Override
public void onComplete(#NonNull Task<ListResult> task) {
if (task.isSuccessful()) {
List<StorageReference> storageReferenceList = task.getResult().getItems();
List<Task<StorageMetadata>> tasks = new ArrayList<>();
storageReferenceList.forEach(item ->
tasks.add(item.getMetadata())
);
Tasks.whenAllSuccess(tasks).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
#Override
public void onSuccess(List<Object> objects) {
for (Object object : objects) {
String title = ((StorageMetadata) object).getCustomMetadata("title");
Log.d("TAG", title);
}
}
});
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
In this way, you'll wait until you have a List full of titles.
You can create a backend API method that returns the list of titles for you in a single call
I know now that your code was demostration purposes only but....
your code says task.getResult().getItems().get(0) meaning that only the first item is being used 150 times
Calling task.getResult().getItems() inside the for, means that you are calling something that only needs to be called once 150 times
Using harcoded 150 instead of the items.length is not a good idea
When you see that your code cumbersome or hard to read, follow the "Single Responsability" to split it into simpler methods.
In the code below I'm using type "Item" because I dont now the name of the type returned by task.getResult().getItems()
void getAllImagesMetadata() {
FirebaseStorage.getInstance().getReference().child("Images/").listAll().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Item []items = task.getResult().getItems() ;
for (int i = 0; i < items.length ; i++) {
title[i] = getTitle(items[i] ;
}
} else {
//Handle error
}
// Make sure the connection to get list of all items is closed here
}
string getTitle(Item item) {
string title ;
item.getMetadata().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
title = task.getResult().getCustomMetadata("title");
} else {
//Handle error
}
// Make sure the connection to get the metada is closed here
return title ;
}
So I am trying to create this page that compares a user's interest with other users and shows the list of all those users.. Now, with the for loop i created, one particular user's name repeats until the end of the loop. I only one one name per username to appear on the textfield.. However, I don't know how to do that.. Here's my code for showing users with common interests:
Realm realm= Realm.getDefaultInstance();
RealmResults<interests> result=realm.where(interests.class).findAll();
RealmResults<Users> user=realm.where(Users.class).findAll();
for(int i=0;i<result.size();i++)
{
for(int j=0;j<result.size();j++)
{
if(result.get(i).getId().equals(userid))
{
if(result.get(i).getInterest().equals(result.get(j).getInterest()))
{
if(!result.get(j).getId().equals(userid)) {
users = result.get(j).getId();
interestss.append("Interests :" + result.get(i).getInterest());
}
}
id.append("\n"+users);
}
}
}
for(int i=0;i<result.size();i++)
{
for(int j=0;j<result.size();j++)
{
if(result.get(i).getId().equals(userid))
{
if(result.get(i).getInterest().equals(result.get(j).getInterest()))
I'm almost 98% sure that you shouldn't even need to write this kind of code if you use Realm's query system and a link query, instead of looping and comparing things manually.
RealmResults<Interests> interests = realm.where(Interests.class)
.equalTo("user.userId", userId)
.findAll();
Which should be possible if you have a backlink from Interests to Users.
// in Interests class
#LinkingObjects("interest")
private final RealmResults<User> user = null;
I know the idea of 'folders' is sort of non existent or different in Google Cloud Storage, but I need a way to delete all objects in a 'folder' or with a given prefix from Java.
The GcsService has a delete function, but as far as I can tell it only takes 1 GscFilename object and does not honor wildcards (i.e., "folderName/**" did not work).
Any tips?
The API only supports deleting a single object at a time. You can only request many deletions using many HTTP requests or by batching many delete requests. There is no API call to delete multiple objects using wildcards or the like. In order to delete all of the objects with a certain prefix, you'd need to list the objects, then make a delete call for each object that matches the pattern.
The command-line utility, gsutil, does exactly that when you ask it to delete the path "gs://bucket/dir/**. It fetches a list of objects matching that pattern, then it makes a delete call for each of them.
If you need a quick solution, you could always have your Java program exec gsutil.
Here is the code that corresponds to the above answer in case anyone else wants to use it:
public void deleteFolder(String bucket, String folderName) throws CoultNotDeleteFile {
try
{
ListResult list = gcsService.list(bucket, new ListOptions.Builder().setPrefix(folderName).setRecursive(true).build());
while(list.hasNext())
{
ListItem item = list.next();
gcsService.delete(new GcsFilename(file.getBucket(), item.getName()));
}
}
catch (IOException e)
{
//Error handling
}
}
Extremely late to the party, but here's for current google searches. We can delete multiple blobs efficiently by leveraging com.google.cloud.storage.StorageBatch.
Like so:
public static void rmdir(Storage storage, String bucket, String dir) {
StorageBatch batch = storage.batch();
Page<Blob> blobs = storage.list(bucket, Storage.BlobListOption.currentDirectory(),
Storage.BlobListOption.prefix(dir));
for(Blob blob : blobs.iterateAll()) {
batch.delete(blob.getBlobId());
}
batch.submit();
}
This should run MUCH faster than deleting one by one when your bucket/folder contains a non trivial amount of items.
Edit since this is getting a little attention, I'll demo error handling:
public static boolean rmdir(Storage storage, String bucket, String dir) {
List<StorageBatchResult<Boolean>> results = new ArrayList<>();
StorageBatch batch = storage.batch();
try {
Page<Blob> blobs = storage.list(bucket, Storage.BlobListOption.currentDirectory(),
Storage.BlobListOption.prefix(dir));
for(Blob blob : blobs.iterateAll()) {
results.add(batch.delete(blob.getBlobId()));
}
} finally {
batch.submit();
return results.stream().allMatch(r -> r != null && r.get());
}
}
This method will:
Delete every blob in the given folder of the given bucket returning true if so. The method will return false otherwise. One can look into the return method of batch.delete() for a better understanding and error proofing.
To ensure ALL items are deleted, you could call this like:
boolean success = false
while(!success)) {
success = rmdir(storage, bucket, dir);
}
I realise this is an old question, but I just stumbled upon the same issue and found a different way to resolve it.
The Storage class in the Google Cloud Java Client for Storage includes a method to list the blobs in a bucket, which can also accept an option to set a prefix to filter results to blobs whose names begin with the prefix.
For example, deleting all the files with a given prefix from a bucket can be achieved like this:
Storage storage = StorageOptions.getDefaultInstance().getService();
Iterable<Blob> blobs = storage.list("bucket_name", Storage.BlobListOption.prefix("prefix")).iterateAll();
for (Blob blob : blobs) {
blob.delete(Blob.BlobSourceOption.generationMatch());
}
Well this question might be too localized.
Lets suppose I have forum system to test. Lets delete an user and his posts. Let me use a pseudo-code for the sake of simplificity:
class User
{
function add() { ... }
function delete (userID)
{
container::getOrCreateUserPostObject.deletePostsByUserID (userID)
DELETE FROM users WHERE ID = userID
}
}
class UserPost
{
function deletePostsByUserID (userID)
{
DELETE FROM posts WHERE USERID = userID
}
}
this now must be tested:
function testDeleteUser()
{
container::getOrCreateUserObject.add();
container::getOrCreateUserObject.add();
container::getOrCreateUserObject.delete (1)
// now check in the DB that how many records left, really one was deleted etc.
}
another test
function testDeletePosts
{
container::getOrCreateUserPostObject.deletePostsByUserID (1);
// again, now check in the DB that how many records left, really one was deleted etc.
}
this looks OK so far. The user deletion and user posts deletion works, and their test standalone.
Yes, standalone. We checked if its OK to delete an user and checked if its OK to delete his post. We didnt check if we delete an user with his posts works! There are two good working "lego" elements but is that OK if we put them together?
If I put this "global" test to testDeleteUser() then I repeat the post-deletion test code...
I don't know if i get you right, but in a test, you should not really rely on specific user id's like you are doing in testDeletePosts(), you should rather add a user here as well, add some posts, and delete these posts again. So your test is completely independent.
Update:
Something like this for checking the referential integrity
function testDeleteUsersAndPosts
{
addedUsers[0] = user.add();
addedPosts[0] = post.add(addedUsers[0], 'first Post')
addedPosts[1] = post.add(addedUsers[0], 'second Post')
addedUsers[1] = user.add();
addedPosts[2] = post.add(addedUsers[1], 'third Post for the second user')
// Check how many posts you have
allPosts = post.get().count()
for (id in addedUsers)
{
user.delete(id)
}
// Check how many posts you have now
allPostsNow = post.get().count();
return allPostsNow == (allPosts -3)
}
And something like this for checking the Post deletion only
function testDeletePosts
{
userID = user.add();
addedPost = post.add(userID, 'first Post')
// Check how many posts you have
allPosts = post.get().count()
post.delete(addedPost)
return post.get(addedPost) == false
}
I am creating a chatbot-like application and I need to know when the application has reached a certain state.
Currently I am using strings to find out what the topic of the conversation is.
Such as
String usersaid = text.toString();
if (usersaid.contains("topic-relevant word") {
execStateRelevantMethod();
}
However I'd like to know if there's a more reliable way to do this. Such as:
if (usersaid.contains("what time is it") {
state.set(timeQuery);
}
if (state == timeQuery) {
execStateRelevantMethod();
}
I have made those state commands up to show you what I'm meaning to ask.