Why can you set a lit public property 'attribute' option to false? - web-component

From the Lit documentation: "The component shouldn't change its own public properties, except in response to user input."
Also from the documentation: "Internal reactive state works just like public reactive properties, except that there is no attribute associated with the property."
However, when you declare a property, there is an option of setting attribute to false, which prevents an attribute from being associated with the property.
#property({attribute: false})
data = {};
What would be the purpose of doing this? Wouldn't the property just act like internal state at that point?
For reference, Lit already has several ways of declaring internal state variables, either with the #state decorator or setting the state option to true, so I'm just not sure why they allow this too.

I think the main use case for this is for when you have to pass big complex data to the component but want it to be set directly as a property and still get lit to rerender stuff for you.
I think this is easier to visualize with an example, let's say you're making a component which will render a list out of an array passed as a property.
If the array was set as an attribute, it would look something like this:
<list-renderer items='[{id: "1", name: "John Doe"}, {id: "2", name: "Alice Williams"}]'></list-renderer>
Now, this example only has two items, but it could be something way bigger, and that attribute will eventually need to be serialized into an array using JSON.parse() by lit. So, you're just doing an extra step, especially if you already had the array as a JS object rather than JSON data.
So, for this kind of cases it's easier to just force users to set items as a JS property directly.
This will also apply for when you need to pass complex configuration setting objects or functions to the component.
Then again, for most of the components you'll be making, you will probably stick with either having the attribute or making it a fully internal state property.

This way you are really free to use any combination.
A property which acts also as state and attribute
A property which acts also as state but not as an attribute
A state, which is not a property
A property, which is an attribute
A property which is not an attribute
see also https://javascript.info/dom-attributes-and-properties for the difference between properties and attributes.

Related

Listener for the JSONModel for Custom Control UI5

i have a custom control which need to array of data as below
properties : {
scrollheight: {type : "sap.ui.core.CSSSize", defaultValue : "100%"},
array1 :{type : "Array", defaultValue : []},
array2 : {type : "Array", defaultValue : []},
}
and i have 3 JSONModel which i have set to the View
Problem is i need to process these model and i have to make 2 arrays to set to the Custom control.
When any change happen to these JSONModels i need to update the array also.
How can i achieve this, if i bind these to property? or do i need to listen the changes to the model and update the array?
or is their any other method of doing it?
i solved this by getting the binding and attaching change event
We have to get the binding for particular item in the Model if its property we can take PropertyBinding if its List or array we have to take ListBinding
and then i have one model which is set to the Custom Control and change event will update the Custom control model
JSBin which shows how to add the change event to binding(Here i used ListBinding)
It is sometimes tough to keep the data in your JSONModel consistent from the controller, as you always have to remember that if you change one thing, you also have to change the other.
To make controller code less cluttered, I usually create a subclass of JSONModel in which I take care of the model consistency. This can be accomplished by overriding the setProperty method with your own, and when you see that a certain property is edited, dependent properties are immediately changed as well.
Please find an example of how this could work in the jsbin below. In the example I'm trying to keep property 2 consistent with property 1:
http://jsbin.com/novepa/1/edit?html,output

Multiple "default" properties/methods in a VB6 class?

I am trying to make a replacement VB6 class for the Scripting.Dictionary class from SCRRUN.DLL. Scripting.Dictionary has (among other things) a "Keys" method that returns an array of keys, and a read/write "Item" property that returns the item associated with a key. I am confused about this, because both of them seem to be defaults for the class. That is:
For Each X In MyDict
Is equivalent to:
For Each X In MyDict.Keys
Which to me implies that "Keys" is the default operation for the class, but:
MyDict("MyKey") = "MyValue"
MsgBox MyDict("MyKey")
Is equivalent to:
MyDict.Item("MyKey") = "MyValue"
MsgBox MyDict.Item("MyKey")
Which to me implies that "Item" is the default operation for the class.
I've never before created a VB6 class that had a default operation, so upon realizing this, I thought perhaps I could define multiple default operations as long as they all have different signatures, which they do: Keys is nullary, the Item getter takes a Variant, and the Item setter takes two Variants. But this doesn't seem to be allowed: When I use "Tools/Procedure Attributes" to set the Keys function to be the default, and then I use it to set the Item property to be the default, the IDE complains that a default has already been set.
So I think I'm misunderstanding something fundamental here. What is going on in the Scripting.Dictionary object that makes it able to act as if "Keys" is the default in some contexts, but as if "Item" is the default in others? And whatever it is, can I accomplish the same thing in VB6?
OK, answering my own question: I haven't tried this yet, but I gather that "Item" should be made the default, and that I should add an entirely new function called "NewEnum" that looks something like the following (slightly modified from an example in Francesco Balena's "Programming Microsoft Visual Basic 6.0" book):
Public Function NewEnum() As IUnknown
Set NewEnum = m_Keys.[_NewEnum]
End Function
(where "m_Keys" is a Collection containing the keys), and then use Tools/Procedure Attributes to hide NewEnum and to set its ProcID to -4.
What you are observing is the difference between the default member and a collection enumerator. A COM object (including VB6 classes) can have both.
You can identify the default property of a class by looking in the Object Browser for the tiny blue globe or the words "default member of" in the description (see Contents of the Object Browser). The Object Browser will not identify an enumerator method, but if you look at the class's interface definition using OLE View or TypeLib Browser (free but registration required) it's DispId will be 0xfffffffc or -4.
In your own class, you can mark the default property by setting the Procedure ID to "(default)" in the Procedure Attributes dialog (see Making a Property or Method the Default). You already listed the steps for setting up the collection enumerator in your own answer, but you can find this listed as well in the Programmer's Guide topic Creating Your Own Collection Class: The House of Bricks.
Scripting.Dictionary has a dirty secret:
It does not handle enumeration at all, it returns big ugly Variant arrays and your For Each loops iterate over those.
This is one of the reasons why a Dictionary can actually be far less efficient than a standard VB6 Collection.

EPiServer: Can I set a dynamic property from code-behind?

I tried to set it as a normal page-property, but no luck.
Guess I could use the DynamicProperty class but I really want to avoid this because of the no-cache issue.
Suggestions anyone?
AFAIK the only way to do this is with the DynamicProperty class. If you look at the documentation on the indexer property on the PageData object it says:
Note! Using this indexer will use the Pre and Post handlers for property lookup. I e return values are not guaranteed to belong to the page, but may be dynamic properties, "fetch-data-from"-data etc. To get data guaranteed to belong to this page, use the GetValueand SetValue methods.
Also note that setting values with this indexer will only set values that acually belong to the page, i e you may get a valid value by reading from the indexer, but trying to set a new value for the same index may yield an exception since the value does not exist in the page.
You will need to use the DynamicProperty class:
DynamicProperty myDynProp = DynamicProperty.Load(CurrentPage.PageLink, "PropertyName");
myDynProp.PropertyValue.Value = "new value";
myDynProp.Save();
Alternatively, you could circumvent the Dynamic Property using an idea Joel discusses here

ASP.NET: Can you use server tags to embed C# or VB.NET expressions into a Javascript function?

I have an enum called SiteTypes that contains several values that are all bound to a dropdown list. On the client side, I need to check this dropdown to see if the selected value is one of those enum values. I don't want to hardcode the value of the enum in the script in case it needs to change, so I want to use a server tag to get it directly from the enum itself. Conecptually, I would like to do this:
function SiteIdChanged() {
var x = "<%=SiteTypes.Employee %>";
}
The way I am doing it now is created a protected property in the codebehind that returns that specific enum value and am doing this:
function SiteIdChanged() {
var x = "<%=EmployeeSiteTypeValue %>";
}
I don't like that, though, because I have to create a special property on every page that I need to do such a check.
Is there a way to do what I want here?
Are you getting a "xxx is inaccessible due to its protection level" error when you compile or run the page? enums are public by default, classes are not. My guess is that you've defined your enum inside your page's class and you aren't explicitly marking it with the 'public' access modifier. Explicitly mark it as public or move it outside of the class and see what happens. If you're planning on using it on lots of pages you should stick the enum definition in in a file in the App_Code folder of your project.
If you don't like your current implementation I would consider using a PageMethod to compare the dropdown selection to the enum value. This approach will probably be cleaner, as you can do most of the logic server-side.
Here's a tutorial on PageMethods:
http://blogs.microsoft.co.il/blogs/gilf/archive/2008/10/04/asp-net-ajax-pagemethods.aspx
As long as your enum is marked public, you can just go with your first option. There's no need to put a property on every single page you want to retrieve the value from.
That approach is really the simplest solution for writing out server side values in your JavaScript.
You can use the Enum.IsDefined Method this well tell you if the selected value from the dropdown is actually part of your enum.
Enum.IsDefined(typeof(MyEnum), myValue)
http://msdn.microsoft.com/en-us/library/system.enum.isdefined.aspx

React to change on a static property

I'm re-writing an MXML item renderer in pure AS. A problem I can't seem to get past is how to have each item renderer react to a change on a static property on the item renderer class. In the MXML version, I have the following binding set up on the item renderer:
instanceProperty={callInstanceFunction(ItemRenderer.staticProperty)}
What would be the equivalent way of setting this up in AS (using BindingUtils, I assume)?
UPDATE:
So I thought the following wasn't working, but it appears as if Flex is suppressing errors thrown in the instanceFunction, making it appear as if the binding itself is bad.
BindingUtils.bindSetter(instanceFunction, ItemRenderer, "staticProperty");
However, when instanceFunction is called, already initialized variables on the given instance are all null, which was the cause of the errors referenced above. Any ideas why this is?
You have 2 options that I am aware of:
Option 1
You can dig into the code that the flex compiler builds based on your MXML to see how it handles binding to static properties. There is a compiler directive called -keep-generated-actionscript that will cause generated files to stick around. Sleuthing through these can give you an idea what happens. This option will involve instantiating Binding objects and StaticPropertyWatcher objects.
Option 2
There is staticEventDispatcher object that gets added at build time to classes containing static variables see this post http://thecomcor.blogspot.com/2008/07/adobe-flex-undocumented-buildin.html. According to the post, this object only gets added based on the presence of static variables and not getter functions.
Example of Option 2
Say we have a class named MyClassContainingStaticVariable with a static variable named MyStaticVariable and another variable someobject.somearrayproperty that we want to get updated whenever MyStaticVariable changes.
Class(MyClassContainingStaticVariable).staticEventDispatcher.addEventListener(
PropertyChangeEvent.PROPERTY_CHANGE,
function(event:PropertyChangeEvent):void
{
if(event.property == "MyStaticVariable")
{
someobject.somearrayproperty = event.newValue as Array;
}
});
I think you need to respond to the "PropertyChanged" event.
If you're going to do that, use a singleton instead of static. I don't think it will work on a static. (If you have to do it that way at all, there are probably a couple ways you could reapproach this that would be better).
var instance:ItemRenderer = ItemRenderer.getInstance();
BindingUtils.bindProperty(this, "myProperty", instance, "theirProperty");
After fiddling with this for a while, I have concluded that this currently isn't possible in ActionScript, not even with bindSetter. It seems there are some MXML-only features of data bindings judging by the following excerpt from the Adobe docs (though isn't it all compiled to AS code anyways)?
You cannot include functions or array
elements in property chains in a data
binding expression defined by the
bindProperty() or bindSetter() method.
For more information on property
chains, see Working with bindable
property chains.
Source: http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_7.html
You can create a HostProxy class to stand in for the funciton call. Sort of like a HostFunctionProxy class which extends from proxy, and has a getProperty("functionInvokeStringWithParameters") which will invoke the function remotely from the host, and dispatch a "change" event to trigger the binding in typical [Bindable("change")] Proxy class.
You than let the HostProxy class act as the host, and use the property to remotely trigger the function call. Of course, it'd be cooler to have some TypeHelperUtil to allow converting raw string values to serialized type values at runtime for method parameters (splitted by commas usually).
Example:
eg.
var standInHost:Object = new HostFunctionProxy(someModelClassWithMethod, "theMethodToCall(20,11)");
// With BindingUtils.....
// bind host: standInHost
// bind property: "theMethodToCall(20,11)"
Of course, you nee to create such a utlity to help support such functionality beyond the basic Flex prescription. It seems many of such (more advanced) Flex bindings are usually done at compile time, but now you have to create code to do this at runtime in a completely cross-platform Actionscript manner without relying on the Flex framework.

Resources