Can I add a promise/unmaterialized record to a hasMany while I wait for it to be retrieved? - ember-data

Back in the unversioned Ember Data days (e.g. "rev 12" maybe) I'm pretty sure you could do this:
var comment = App.Comment.find(42); // Already exists, but not yet loaded...
post.get('comments').addObject(comment);
Because App.Comment.find(42) would return an App.Comment object, albeit one with no fields populated except it's ID. (I don't remember the details of how you'd then save the App.Post--i.e. if you could or couldn't save it until the comment object was completely loaded…I never got that far.)
Why this was neat is that if your template rendered post.comments, a new row/div would appear immediately that could check isLoaded to display a loading indicator and show instantly that a new record was attached while waiting for the record's data to load. This is/was a selling point of Ember/Ember Data, and one I really like.
But this doesn't work now in 1.0.0-beta.2 beta.4 beta.5:
var comment = controller.get('store').find('comment', 42);
post.get('comments').addObject(comment); // Fails
Because controller.get('store').find('comment', 42) returns a promise, and if I try to add it to the hasMany it complains that I can only add App.Comment objects to the relationship.
Is it still possible to do something like this, so that my template which renders the comments immediately updates with a new record, but asynchronously populates its data?
(Please ignore that it doesn't make sense to add an already existing comment to a post--using the ubiquitous example scenario is easier than posting all my model code. Thanks!)

Okay, I came up with at least one way that does it:
var comment = controller.get('store').find('comment', 42);
var inFlightRecord = controller.get('store').getById('comment', 42);
controller.get('comments').addObject(inFlightRecord);
To be safer, maybe:
var comment = controller.get('store').find('comment', 42);
var inFlightRecord = controller.get('store').getById('comment', 42);
if(inFlightRecord){ // should be null if it isn't in the store
controller.get('comments').addObject(inFlightRecord);
} else {
// add a then block to the promise to make sure it gets added later
}
It seems that getById returns the "unloaded" object like we used to get from App.Comment.find(42), and the object still has an isLoaded property you can check to show loading status in your template.
I'm not sure if this is supposed to be supported behavior that I can rely on going forward (I suppose arguably nothing is, until 1.0 release), but it seems to work. I even checked that the object returned by getById === the object fulfilled in the promise. So this seems to be a good solution.
Anyone see a problem with this, or have a better way?

Related

Iterating store in relay optimisticUpdater

Apologies in advance, I'm new to relay and not sure I've got all the terminology here right...
I have a (simplified) graph that looks like:
customer {
summary(id: "ABC123") {
records { // This is an array of Record
tag
}
}
}
Customer, Summary and Record are all objects with global IDs - they show up as records in the Relay DevTools inspector.
I have a mutation that removes a tag by name (from elsewhere in the graph - not shown), from which I need to update the customer summary object to remove the record with associated tag. I have tried two approaches and not gotten very far with either:
Re-request customer.summary as part of the mutation. The problem is I don't know what the ID is at that point. (Maybe I can thread it through some how, but that would be messy.) Also doesn't really solve the problem, since I'd like to do this optimistically.
In an optimistic updater, remove any tag record that matches. This seems like it should work, but the RecordProxy doesn't appear to have a rich enough API to enable me to do this.
First approach, I can't seem to get access to the summary record via the root:
const customer = store.getRoot().getLinkedRecord('customer') // works!
customer.getLinkedRecord("summary") // undefined
customer.getLinkedRecord("summary", {id: "ABC123"}) // undefined
Second approach, if I could ask the store for "all records of type" or even "all records" I could iterate through and find the one I need to edit, but this doesn't seem to be a method that's exposed (even though Relay DevTools must be doing it somehow).

Re-enable load on demand [NativeScript Vue]

I have a Radlistview, where the data switches out based on user query. With loadOnDemandMode="Auto" and when the current query is exhausted, I then call notifyLoadOnDemandFinished(true). However, when a new query is made, I cannot re-enable loadOnDemand, and new items are not loaded.
Is there a way to reactivate loadOnDemand, perhaps with a method on the radListView object? I couldn't find anything in the docs.
Found the mistake, posting here for anyone else that may have the problem.
I was trying to set
listView.loadOnDemandMode = "Auto"
adding _nativeView fixed it
listView._nativeView.loadOnDemandMode = "Auto"

FPM - WD - LPD: POWL as Listpopup to choose a record and then return it

The situation is like this:
We have a POWL, where I added a toobar-button.
The click on that button opens a FPM-POWL, which I created
with the help of this link
https://sapcodes.com/2016/03/25/powl-in-fpm/....
(INFO: This POWL takes it's data from a standard FBI View).
The new FPM-POWL is properly(??? I hope so, because it gets shown) maintained inside the LPD_CUST in order to start this popup inside the FPM-framework (flag that it should wait, is also set on caller and callee) .
Ok, let's proceed.--
The calling class (feeder class "A", implementing IF_POWL_FEEDER) calls the POPUP like this
DATA(lt_lpd_content) = lr_lpd_handle->mt_content.
READ TABLE lt_lpd_content
REFERENCE INTO DATA(lr_lpd_content)
WITH KEY application_alias = 'ZSRM_GP/BP_POPUP'.
lr_lpd_handle->launch_application( iv_application_id = lr_lpd_content->application_id ).
The user shall simply be able to pick one business partner....
After the user picks a record, and hits a special toolbar-button of the "popup", its feeder class "B"(also implementing IF_POWL_FEEDER) does, what it needs to do inside handle_action and until now... I try to figure out, HOW to pass the record back to the caller class "A"...
Because, unlike expected (because both LPD_CUST entries have the flag set "Synch/await"), the class "A" proceeds processing any code I place after
lr_lpd_handle->launch_application( iv_application_id = lr_lpd_content->application_id ).
And so I suppose, this is "works as designed" and is asynchroneous .
So, my current experiments assumed synchroneous, and I exported any picked business partner's number to a memory ID and closed the "popup".
But I never returned to the caller, where I wanted to start coding the rest of the requirement.
So, my second try is, that I created an event in feeder class "B" (called popup) and a handler for this inside feederclass "A" ( caller ).
Inside the ctor of class "A" I register via "SET HANDLER FOR ALL INSTANCES".... and the tests are just about to start.
But I really hate this approach,.... is there a best practice regarding this ?
I cannot imagine, that I am the only one with this kind of requirement, which, in simple terms, means:
"Listpopup"... and we all know, how simple this is in sapgui...but inside the FPM-POWL-LPD environment... I cannot get it...
EDIT: Maybe I should do something in here to FORCE a blocking popup call ?
Or can I somehow populate the exporting parameters of handle action of the callee to return to the callers handle_action ? Ala POWL_FORWARD_anything ?

Whats wrong with my code (GML)

ok so im sorry to be asking, however im trying to make it so that when i press z, a portal appears at my Spr_players coordinates, however if one of them already exists, i want it to be erased and im simply wondering what ive done wrong. Again sorry for bothering. (please note that i am a bad programmer and i appoligize if i broke any rules)
if object_exists(portal)
{
instance_destroy()
action_create_object(portal,Spr_player.x,Spr_player.y)
}
else
{
action_create_object(portal,Spr_player.x,Spr_player.y)
}
The instance_destroy() statement destroys the current self instance which is what is executing the code. You must use the with (<objectID>) {instance_destroy()} syntax to destroy another instance.
As long as there is only one instance of portal in the room this code should work:
if object_exists(portal)
{
with (portal) instance_destroy(); //you should also need a semicolon here to separate
//this statement from the next, it is good practice
//to do this after all statements as I have done.
action_create_object(portal,Spr_player.x,Spr_player.y);
}
else
{
action_create_object(portal,Spr_player.x,Spr_player.y);
}
If there are multiple instances of portal this will only destroy the first one. To destroy all you would have to use a for loop to iterate through them all. Off the top of my mind I can not remember the function to get the ids of all the instances of an object, but it looks like this is not a problem since each time one is created the existing one is destroyed and thus you will only have one a t a time.
Another way of doing this is just to move the existing portal to the new position. The only difference here is that the create event of the portal will not be executed and any alarms will not be reset.
portal.x=Spr_player.x
portal.y=Spr_player.y
Again this will only move the first portal if there are more than one.

Phalcon redirection and forwarding

Do I understand correctly that after doing $this->dispatcher->forward() or $this->response->redirect() I need to manually ensure that the rest of the code does't get executed? Like below, or am I missing something?
public function signinAction()
{
if ($this->isUserAuthenticated())
{
$this->response->redirect('/profile');
return;
}
// Stuff if he isn't authenticated…
}
After almost a year of working on a hardcore project that uses Phalcon beyond its capacity, I wanted to clarify a few things and answer my own question. To understand how to properly do redirects and forwards you need to understand a little about how the Dispatcher::dispatch method works.
Take a look at the code here, though it's all C mumbo-jumbo to most of us, its really well written and documented. In the nutshell this is what it does:
The dispatcher enters the while loop until the _finished property becomes true or it discovers a recursion.
Inside the loop, it immediately sets that property to true, so when it starts the next iteration it will automatically break.
It then gets the controller / action information, which are originally supplied by the router in the application, and does various checks. Before and after that it also completes a lot of event-related business.
Finally it calls the action method in the controller and updates the _returnedValue property with (guess what!) the returned value.
If during the action call you call Dispatcher::forward method, it will update the _finished property back to false, which will allow the while loop to continue from the step 2 of this list.
So, after you do redirect or forward, you need to ensure that you code doesn't get executed only if that is part of the expected logic. In other words you don't have to return the result of return $this->response->redirect or return $this->dispatcher->forward.
Doing the last might seem convenient, but not very correct and might lead to problems. In 99.9% cases your controller should not return anything. The exception would be when you actually know what you are doing and want to change the behaviour of the rendering process in your application by returning the response object. On top of that your IDE might complain about inconsistent return statements.
To finalise, the correct way to redirect from within the controller:
// Calling redirect only sets the 30X response status. You also should
// disable the view to prevent the unnecessary rendering.
$this->response->redirect('/profile');
$this->view->disable();
// If you are in the middle of something, you probably don't want
// the rest of the code running.
return;
And to forward:
$this->dispatcher->forward(['action' => 'profile']);
// Again, exit if you don't need the rest of the logic.
return;
You need to use it like this:
return $this->response->redirect('/profile');
or
return $this->dispatcher->forward(array(
'action' => 'profile'
))
Use send() like this
public function signinAction()
{
if ($this->isUserAuthenticated())
{
return $this->response->redirect('profile')->send();
}
}