Binding, Context, ContextBinding and BindingContext in ui5 - sapui5

I have been pondering the internals of and relationship between context, contextbinding, and bindingcontext for a few days now and i am not sure whether there is a major misconception on my side. Maybe some of you can help me sort it out. I am putting my assumptions below. I might want to say first that I always work with oData models here.
This is what I believe to understand reading the documentation:
A context is a reference to a data object in a model.
A binding is basically an event provider which (in case of a one way binding) observes the status of a specific context and emits events when it is changed/data loaded ... and therefore allows for registering event handlers for events on that specific context. In terms of programming objects, there are property bindings and list bindings (is this true - or is list binding all that is ever relevant?).
At any rate, my understanding is that a list binding is the model-side of a component's aggregation binding, while a property binding is called property binding both from a component's and a model's point of view (confusing?).
Now what I do not quite get is:
The context binding new sap.ui.model.ContextBinding(oModel, sPath, oContext, mParameters?, oEvents?): takes a path and a context as a parameter. I am assuming that this oContext is not exactly the context described above but some metadata on the binding. is this correct? Or is this the definition of thep ath which the path parameter is relative to?
What also seems weird is when you want to create a context itself new sap.ui.model.Contextabov(oModel, sPath, oContext) takes a context again.
I believe that this is just an unfortunate naming thing i am looking at, but I am not quite sure.
Then there is contextbinding and bindingcontext. I'd assume that contextBinding is the binding to a specific context as described e. And a bindingcontext is the meta data regarding a context- or list binding.
From a programming point of view, I do not understand why the following works:
create list binding to context via model.bindList() passing a path only.
attach change-event handler to binding
call get_contexts() on binding
receive data in change event handler (and see the oData-property filled in the model).
and there seems to be no way of doing the same for a property binding which i'd assume I can generate via model.bindProperty(). I can generate the binding, but the binding I receive seems to have no handle to actually fetch data.
I hope the ramble explains my problem. In case you ask : what do you want to do? I actually do not want to do anything with it, I just do not quite understand how this works. Binding to ui controls and so forth works just fine, but I'd prefer to really understand what is underneath the hood. I have been reading debug files and unit tests a bit, but discussing it with you guys seems a great way as well.
If this is unclear I'll happily add anything that helps.
Cheers
Michel

your questions are answered below. Hope it helps.
Now what I do not quite get is: The context binding new sap.ui.model.ContextBinding(oModel, sPath, oContext, mParameters?, oEvents?): takes a path and a context as a parameter. I am assuming that this oContext is not exactly the context described above but some metadata on the binding. is this correct? Or is this the definition of thep ath which the path parameter is relative to?
the oContext is the context you mentioned above, to be precise, is sap.ui.model.Context.
What also seems weird is when you want to create a context itself new sap.ui.model.Context(oModel, sPath, oContext) takes a context again. I believe that this is just an unfortunate naming thing i am looking at, but I am not quite sure.
I guess the documentation here confused you. Actually, sap.ui.model.Context only takes oModel and sPath as parameters. The following code is what i get from sap-ui-core.js. You can see the JSDoc part about parameters is actually inconsistent with the code. Maybe there is some kind of typo there.
/**
* Constructor for Context class.
*
* #class
* The Context is a pointer to an object in the model data, which is used to
* allow definition of relative bindings, which are resolved relative to the
* defined object.
* Context elements are created either by the ListBinding for each list entry
* or by using createBindingContext.
*
* #param {sap.ui.model.Model} oModel the model
* #param {String} sPath the path
* #param {Object} oContext the context object
* #abstract
* #public
* #name sap.ui.model.Context
*/
var Context = sap.ui.base.Object.extend("sap.ui.model.Context",
/** #lends sap.ui.model.Context.prototype */ {
constructor : function(oModel, sPath){
sap.ui.base.Object.apply(this);
this.oModel = oModel;
this.sPath = sPath;
},
metadata : {
"abstract" : true,
publicMethods : [
"getModel", "getPath", "getProperty", "getObject"
]
}
});
From a programming point of view, I do not understand why the following works:
create list binding to context via model.bindList() passing a path only.
attach change-event handler to binding
call get_contexts() on binding
receive data in change event handler (and see the oData-property filled in the model).
and there seems to be no way of doing the same for a property binding which i'd assume I can generate via model.bindProperty(). I can generate the binding, but the binding I receive seems to have no handle to actually fetch data.
Actually you can also attachChange event to sap.ui.model.PropertyBinding, and you can call getValue() to get the data.

Thanks, Allen, that really helped. It really mainly was a confusion regarding the documentation and the getValue slipped me as well.
To add another answer to a question only implicitly included in the title:
context binding: the binding you set up to a given path.
binding context: the context of a given binding, i.e. when coming from a component, or some other set up binding.
Cheers
Michel

Related

AEM - How to cache model for page scope?

I have a sling-model that needs to do some costly operations at initialization. These are related to the page scope, meaning based on currentPage properties. Hence it would make sense that the model gets initialized only once per page call.
I found a nice article regarding this at how to call sling model only once where they are setting the cache property of the Model-annotation to true.
But this unfortunately only works per resource.
So setting the cache=true property the model gets initialized for every component that calls it via data-sly-use. It only helps wenn calling data-sly-use in the same component (resource), but that's not helpful.
Can I somehow have the model cached for the entire lifecycle of the page-request?
SlingHttpServletRequest is a wrapper around HttpServletRequest and supports setAttribute and getAttribute methods provided by servlet api.
Setting attributes:
slingRequest.setAttribute(ATTRIBUTE_NAME, myobject);
Retrieve:
//check for null
MyClass myobject = (MyClass) slingRequest.getAttribute(ATTRIBUTE_NAME);

What and when can "Target" be instead of an Entity and should I check its logical name when working on a single entity type?

I'm a newbie in developing in CRM, so I want to get some things clear. And you first you need to know the reason why you have to do something in order to fully understand it. So lets get to the question.
I know you have to do this when making a plugin:
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.InputParameters.Contains("Target") && context.InputParameters.["Target"] is Entity)
{
var entity = (Entity)context.InputParameters["Target"];
if(entity.LogicalName == "myEntity")
{
//Do something with your entity
}
}
Now, in the PluginRegistration Tool, you can set up that your plugin will be fired on the defined Message and which entities (and specific attributes from them) will be affected by it, besides other stuff.
I can see the validations are very useful when manipulating several entities with a single plugin.
Now, let's suppose you only are updating a single entity with your plugin. Why should I check if the entity that's on "Target" is the entity I want to work on, if I already know because I set it up for that entity in particular? What can an Entity be otherwise in that scenario?
Also, in what cases "Target" is NOT an Entity (in the current context)?
Thanks in advance, and sorry if this is a silly question.
See this answer: Is Target always an Entity or can it be EntityReference?
Per the SDK (https://msdn.microsoft.com/en-us/library/gg309673.aspx):
Note that not all requests contain a Target property that is of type
Entity, so you have to look at each request or response. For example,
DeleteRequest has a Target property, but its type is
EntityReference.
The bottom line is that you need to look at the request (all plugin's fire on an OrganizationRequest) of which there are many derived types (https://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.organizationrequest.aspx) to determine the type for the Target property.
As Nicknow said, the Input Parameters will change depending on the Message being executed.
You can get that information from the MSDN (every request will list the Input Parameters under the Properties section, for instance the CreateRequest) or using the ParameterBrowser.
There's also a really nice alternative to deal with this in a type-safe approach (intellisense included) described in the following blog article: mktange's blog.

Are UE4 Blueprints the same with a C++ class? If so, how will I implement a class design?

Good day! I am new to using Unreal Engine 4 and I have a few questions about how exactly blueprints work. From my understanding of it, every blueprint works like a class. By that I mean one blueprint is much like one class in an OOP programming language.
Please educate me as to - if my assumption is correct or wrong. If wrong, then maybe you could help me achieve what I want in a different method/perspective. I am willing to learn and accept suggestions.
If at some point my understanding is correct - that blueprints are actually individual classes - I would really appreciate it if you could (please) guide as to where to go and how to implement a design that I want to create. This is from a programmers perspective (PHP OOP Programming). Forgive the approach, I'm just using PHP to logically express how I want the class to work. Plus, it is the only OOP programming I know atm.
I want to create a class named: Items. class Item {}
This class is going to handle everything item related, thus we will have to give it a lot of properties/variable. (Below is just an example; Again I'm using PHP as an example.)
class Item {
var $id;
var $name;
var $description;
var $type;
var $subType;
var $mesh;
var $materials;
}
3.) I would like to initiate this class by having two variables as its construct arguments. (We will require itemID and itemType). This is because I will use these two variables to retrieve the item's data which is already available in a data table. I will use those data in the table to populate the class properties/variables. (I'm not sure if I said that right. I hope you understood my point anyway.)
class Item {
var $id;
var $name;
var $description;
var $type;
var $subType;
var $mesh;
var $materials;
function _construct($cons_itemID, $cons_itemType) {
/*-- Start getting the item Data here based on what item and type provided. Then, push that data into the class properties/variables. We will use individual methods/functions to fill other properties/variables later. --*/
}
}
4.) Basically with that design I could easily pass on an item ID to the class and then get the item's name, description, mesh, materials and etc using pointers.
Example:
$weapon = new Item('10001','Weapon');
$weaponMesh = $weapon->getMesh();
$armor = new Item('12345','Armor');
$armorName = $armor->getName();
I'm just having a lot of trouble working with blueprint and achieve this method or even something similar to it. I'm not trying to avoid C++, I would love to learn it but I just don't have the time freedom right now.
Few things I have tried to make it work:
Casting / Casting to class (But I couldn't figure out what the target object will be and how was I going to add input arguments into the class that way? There isn't any input there that I could use.)
Spawn Actor (This one is very promising, I need to dig in deeper into this)
Blueprint Macros? Blueprint Interfaces? (I'm just lost.)
For all those who will help or answer. Thank you!
~ Chris
So far as I know, yes, we can assume that each blueprint can be viewed as class. (Moreover, since UE 4.12 (in UE 4.11 that functionality is marked as experimental I think) you can check Compile blueprints under Project settings -> Packaging. That will create native class for each blueprint.)
You can create either Blueprint or C++ class based on Object (UObject in C++). Then you can specify all properties (or variables in UE editor terminology). In BP you have small advantage: you can mark some properties as Visible at spawn (they must be Public and Visible). So when you are creating new instance of that class, you can explicitly pass values to that properties.
And in BP Construct event, that properties are correctly filled, thus you can set another properties values based on given ID and Type.
In C++ class having different arguments than FObjectInitializer is not possible, thus you don't have that values in time when constructor is executed. But it is not so hard to achieve same functionality, you can find example here: https://answers.unrealengine.com/questions/156055/passing-arguments-to-constructors-in-ue4.html.
Something about list of what you had tried:
Spawn actor - derive from actor only if you intend to have that BP in scene. Actors are subjects to game updates and rendering, so having actor only as data container is very wrong.
BP Macro is same as BP Function except function will be called just like function (so executing necesary actions by function call conventions) and macro will replace it's implementation in place, where you are calling that macro. More exhausting explanation here.
If I would implement your code, I'd do it like I said and then I'll have that class as property in some component and that component would be attached to some actor, which would be placed in scene.

Does symfony have a built-in method for comparing tainted values to the original?

I am using symfony 1.4 with Doctrine. I have built a form which uses a table that has the Versionable behaviour. As expected, Versionable creates a new version of the row every time the form is submitted and saved. My problem is that I would like to prevent it doing so if the actual values submitted are not any different from the original values put into the form via the edit action.
I know that I can do this with javascript relatively easily. I'm just curious as to whether symfony or Doctrine have this functionality already, and how it is used if so. It just seems like something that symfony would have a method for, which could be checked right before $form->save() is called. Am I dreaming or perhaps missing something obvious?
You can use the DoctrineRecord::getModified() function which returns an array of the modified fields and associated values from an overridden save() function or in a listener (preSave would be the best I guess).
If the new values are not any different, you can bypass the actual call to save(), so no new version is created.
The comment for the save() method of the Doctrine_Record is
/**
* applies the changes made to this object into database
* this method is smart enough to know if any changes are made
* and whether to use INSERT or UPDATE statement
*
* this method also saves the related components
*
* #param Doctrine_Connection $conn optional connection parameter
* #throws Exception if record is not valid and validation is active
* #return void
*/
so first, you should check whether it does not already work.
If not, Doctrine_Record has a isModified() method you could use. If the bind() method of the form object modifies the object in the form which should at first contain the default values, then this method should return true.
If you don't want to override save() method or implement a listener as jaudette suggested you can instead stay with form binding:
$form->bind($values);
if ($form->isValid()) {
$form->updateObject();
$changes = $form->getObject()->getModified();
// save to database if desired
$form->save();
}
The object will not be saved to database by calling $form->updateObject(), but the actual php object is changed.
Also note that you might have to call getModified() on each related object if you have embedded subforms.

zend_form access parent form element

I couldn't find any reference on how to use a parent form element in a subclassed form. May be because it's obvious to everyone but me. It's got me stumped. This is what I tried.
At first, within my form constructor I called
parent::__construct($options = null);
then accessed the parent elements like this
$type = parent::setName($this->type);
The problem was that ALL the parent form elements would display whether explicitly called or not. Someone said, "don't use __construct(), use the init() function instead. So I changed the constructor to init(), commented out the parent constructor, then ran the form. It bombed saying it couldn't pass an empty value for setName(). I commented out all the seName() calls and the form ran, but only displayed the elements instantiated in the subclassed form.
My question is this: If I don't use the parent constructor, how do i get and use the parent's form elements?
Solved: Since the constructor was switched to init, the call to the parent also needed to be switched. Easy for someone with php background. Not so much for one who doesn't.
Use
parent::init();
Solved: Since the constructor was switched to init, the call to the parent also needed to be switched. Easy for someone with php background. Not so much for one who doesn't.
Use
parent::init();
You should learn OOP principles first. Obviously you have no understanding of it whatsoever. You need to call parent::init() in you Form_Class::init() method as you wrote, but why? Because otherwise the parent method is not called and is overriden by the From_Class method.
Other thing is that when you have a parent class "SuperForm" with input and submit, then your "SuperForm_Subclass" would have the same elements assigned. There is no need to use "parent::*" to access element (only exception would be if you used static SuperForm variable to store them - which makes no sense).
You can easily use $this->inputElement and $this->submitElement inside your SuperForm_Subclass like you would in the SuperForm class.
In your example you could used the __contruct() as good, but with the same condition of calling the parent constructor. You would be able to access elements generated there too...