Passing variables to child component, and getting NaN returns - flex3

I have a component being called within a repeater. Within the call, i'm passing several variables to the component. All of them work fine except for one named totalSpan... which is returning a NaN for some reason. Here's the code I'm working with:
Parent:
<mx:Repeater id="indPositions" dataProvider="{projectPositions}" startingIndex="0" count="{projectPositions.length}">
<components:block height="28"
id="thisBlock" visible="true" horizontalScrollPolicy="off"
width="{projectWidth}"
oneDay="{Number(oneDay)}"
offSet="{indPositions.currentItem[0]}"
numDays="{indPositions.currentItem[1]}"
position="{indPositions.currentItem[2]}"
sName="{indPositions.currentItem[3]}"
projectName="{projectTitle}"
totalSpan="{Number(Math.round(projectWidth.vl / oneDay))}"
/>
</mx:Repeater>
All of the variables in there work fine and will typeof() just fine.
Here's the child code:
[Bindable] public var totalSpan:Number;
and then in the init() function I perform a simple:
Alert.show(String(totalSpan));
The alert returns "NaN".
On a semi-related note, i'm getting warnings on the following lines of the parent:
offSet="{indPositions.currentItem[0]}"
numDays="{indPositions.currentItem[1]}"
position="{indPositions.currentItem[2]}"
sName="{indPositions.currentItem[3]}"
with an message that says "Data binding will not be able to detect chances when using square bracket operator. For Array, please use ArrayCollection.getItemAt() instead.
Can anybody shed some light on these warning errors? an example would be greatly appreciated.

First of all the assignment of totalSpan is the following:
totalSpan="{Number(Math.round(projectWidth.vl / oneDay))}"
but from width="{projectWidth}" we can see projectWidth is a Number or int. So it hasn't vl property. And your Number(Math.round(projectWidth.vl / oneDay)) is NaN. Please rewrite it properly. Maybe it should be the following:
totalSpan="{Number(Math.round(projectWidth / oneDay))}"
About the second part. If you're using {} in MXML it stands for data binding. Data binding provides changes in target attributes with changes of source. And the message says Array is a primitive type and mxmlc compiler can't generate code for it to handle changes in array's values.
But it is obvious from code you have some problems with data structures. It is very hard to improve it do not having the whole project's code but you should use custom data types with required [Bindable] metadata for data binding and ArrayCollection instead of Array for data used as a source of data binding.
Try to create something like:
[Bindable]
class MyDataObject
{
public var offSet:int;
public var numDays:int;
public var position:int;
public var sName:String;
}
and put these items to data provider of your repeater. As far as I can understand now your data provider is for repeater length but in real life it should provide repeater elements data. So if you pass into your repeater an ArrayCollection of your custom MyDataObject objects you can use something like the following:
<mx:Repeater id="indPositions" dataProvider="{projectPositions}">
<components:block height="28"
id="thisBlock" visible="true" horizontalScrollPolicy="off"
width="{projectWidth}"
oneDay="{Number(oneDay)}"
offSet="{indPositions.currentItem.offSet}"
numDays="{indPositions.currentItem.numDays}"
position="{indPositions.currentItem.position}"
sName="{indPositions.currentItem.sName}"
projectName="{projectTitle}"
totalSpan="{Number(Math.round(projectWidth / oneDay))}"
/>
</mx:Repeater>
And even more. You can pass the whole object of MyDataObject type to your components:block component:
<mx:Repeater id="indPositions" dataProvider="{projectPositions}">
<components:block height="28"
id="thisBlock" visible="true" horizontalScrollPolicy="off"
width="{projectWidth}"
oneDay="{Number(oneDay)}"
myData="{MyDataObject(currentItem)}"
projectName="{projectTitle}"
totalSpan="{Number(Math.round(projectWidth / oneDay))}"
/>
</mx:Repeater>
Hope these thoughts help!

Related

IValueConverter – Passing an object as ConverterParameter

In my Xamarin xaml file I have a ProgressBar, where I need to compute Progress (Value/Maximum). So I wrote my Convertor, but I am not able to pass the Maximum to the Convertor.
I tried to use ConverterParameter, but it does not support bindings...
<ProgressBar Progress="{Binding Progress.Value,
Converter={StaticResource Convertor}, ConverterParameter=??}" />
Am I doing something wrong or is there any workaround?
You could pass a reference directly into your converter if it's defined in xaml of whatever class/ViewModel that has all the values you need to calculate progress.
<ProgressBar x:Name="_progressBar" Progress="{Binding Progress.Value,
Converter={StaticResource Convertor}, ConverterParameter={x:Reference _progressBar}}" />
or you could just pass in the value directly in xaml or as a static value defined in a static class from elsewhere in your app, which is of course if you know what the value will be ahead of time.
, ConverterParameter=1}" or
, ConverterParameter={x:Static local:DefaultValues.MaxValue}}"
However, it does sound like you could calculate Progress in your ViewModel on property changed before setting Progress.Value/Progress.MaxValue property, and then you wouldn't even need a converter.

InputScope dependency property, XAML designer problems + errors

I have a control that consists of a button and a textbox.
I wanted to set the input scope of the textbox, so I introduced a new dependency property:
public InputScope InputScope
{
get { return (InputScope)GetValue(InputScopeProperty); }
set { SetValue(InputScopeProperty, value); } // Notify prop change
}
public static readonly DependencyProperty InputScopeProperty =
DependencyProperty.Register(nameof(InputScope), typeof(InputScope), typeof(SearchControl), new PropertyMetadata(DependencyProperty.UnsetValue));
In XAML:
<controls:SearchControl InputScope="Number" /> <!-- etc... -->
(Obviously assigning it to the InputScope property of the textbox in the style of this custom control.)
My problem: While this works, the numeric keyboard gets shown when focused, but I have blue underline in the XAML, and also an error message: The TypeConverter for "InputScope" does not support converting from a string.
Is there a way to fix it without a dirty hack?
Is there a way to fix it without a dirty hack?
You could implement a type converter. Please refer to Tim Heuer's blog post for more information and an example:
Implementing a type converter in UWP XAML: http://timheuer.com/blog/archive/2017/02/15/implement-type-converter-uwp-winrt-windows-10-xaml.aspx
You may also want to read this:
WinRT Replacement for System.ComponentModel.TypeConverter

Binding list to a HTML textbox is not updating the view

In Aurelia, I have a textbox like this:
<input type="text" value.bind="contact.topics|commaList">
Where commaList is a value converter:
export class CommaListValueConverter {
toView(value) {
return value.join('|')
}
fromView(value) {
return value.split('|')
}
}
There are two things:
Updating the list (contact.topics) from code doesn't change anything in the view. Tried forcing two-way as well. The toView() is not called (tried to log calls). For comparison, in my view there is also a regular repeat topic of contact.topics which update fine.
Aurelia modifies my contact.topics list by adding an element __array_observer__: ModifyArrayObserver to my list. So now I somehow have to clean my list of such unwanted elements before saving (or dirty checking).
I update the array this way:
this.contact.topics.push('test')
The contents of the array display correctly in the for of loop (not shown).
gist
https://gist.run/?id=dd11c5837b77b29b586d2c4f978a7a48
Aurelia bindings don't react on Array and Object internal changes unfortunately.
You can't escape the __ private properties that aurelia adds for observation but since you are dirty checking an array you can take a clean clone of it with arr.slice()

Polymer 1.0 Data binding when object changes

I'm having trouble understanding how data-binding works now.
On my index page I've got an object (obtained as JSON from a RESTful service), which works just fine when applied to a custom element like:
<main-menu class="tiles-container ofvertical flex layout horizontal start"
menuitems="{{menuitems}}">
</main-menu>
var maintemplate = document.querySelector('#fulltemplate');
maintemplate.menuitems = JSON.parse(data.GetDesktopResult);
This works as expected, and when I load my page with different users, main-menu changes as it should to show each user's desktop configuration. (This menuitems object reflects position and size of each desktop module for each user).
Now, users used to be able to change their configuration on the go, and on Polymer 0.5 I had no problem with that, just changed my maintemplate.menuitems object and that was that, it was reflected on the template instantly.
As I migrated to Polymer 1.0, I realized changes on an object wouldn't change anything visible, it's much more complicated than this, but just doing this doesn't work:
<paper-icon-button id="iconback" icon="favorite" onClick="testing()"></paper-icon-button>
function testing(){
debugger;
maintemplate = document.querySelector('#fulltemplate');
maintemplate.menuitems[0][0].ModuleSize = 'smamodule';
}
The object changes but nothing happens on the screen until I save it to DB and reload the page.
Am I missing something /Do I need to do something else on Polymer 1.0 to have elements update when I change an object passed as a property?
Before you ask, I've got those properties setted as notify: true, it was the inly thing I found different, but still doesn't work
Thanks for reading!
EDIT:
this is the code menuitems is used in:
<template is="dom-repeat" items="{{menuitems}}" as="poscol">
<div class="positioncolum horizontal layout wrap flex">
<template is="dom-repeat" items="{{poscol}}" as="mitem" index-as="j">
<main-menu-item class$="{{setitemclass(mitem)}}"
mitem="{{mitem}}"
index="{{mitem.TotalOrder}}"
on-click="itemclick"
id$="{{setitemid(index, j)}}">
</main-menu-item>
</template>
</div>
</template>
main-menu-item is just set of divs which changes size and color based on this object properties
You need to use the mutation helper functions if you want to modify elements inside an object or array otherwise dom-repeat won't be notified about the changes (check the docs):
function testing(){
debugger;
maintemplate = document.querySelector('#fulltemplate');
this.set('maintemplate.0.0.ModuleSize', 'smamodule');
}

clear my Flex Queries

I just started learning Flex these days.. I just had one doubt: below is the code:
Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<s:layout>
<s:VerticalLayout paddingLeft="10" paddingTop="10"/>
</s:layout>
<fx:Style source="Styles.css" />
<fx:Script>
<![CDATA[
import components.NameDisplay;
import spark.skins.spark.DefaultComplexItemRenderer;
import spark.skins.spark.DefaultItemRenderer;
private function rendererFunction(item: Object): ClassFactory
{
if(item is String)
return new ClassFactory(NameDisplay);
else
return new ClassFactory(DefaultComplexItemRenderer);
}
]]>
</fx:Script>
<fx:Declarations>
<s:ArrayList id="employeeList">
<fx:String>Samuel Ang</fx:String>
<s:BitmapImage source="images/sang.jpg"/>
<fx:String>Athena Parker</fx:String>
<s:BitmapImage source="images/aparker.jpg"/>
<fx:String>Saul Tucker</fx:String>
<s:BitmapImage source="images/stucker.jpg"/>
<fx:String>Alyssa Le</fx:String>
<s:BitmapImage source="images/ale.jpg"/>
</s:ArrayList>
</fx:Declarations>
<s:Label text="Employee Portal: Employee Directory"
styleName="titleHeader"/>
<s:DataGroup dataProvider="{employeeList}"
itemRendererFunction="rendererFunction">
<s:layout>
<s:VerticalLayout paddingLeft="15" paddingTop="15"/>
</s:layout>
</s:DataGroup>
</s:Application>
NameDisplay.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Label text="{data}"
width="74" height="30"
backgroundColor="#000000"
color="#FFFFFF"
textAlign="center"
verticalAlign="middle" />
</s:ItemRenderer>
My Doubts:
1) How does my 'rendererFunction' code returns a ItemRenderer at end? I mean how does ClassFactory returns a ItemRenderer object? I checked ClassFactory.as code, I have seen newInstance() method (which was implemented from IFactory interface), so how does ClassFactory calls automatically newInstance() method (actually, iam guessing that iam getting ItemRenderer object via newInstance() method)
2) Inside DisplayName.mxml code: <s:Label text="{data}" , I found that this 'data' coming from DataRenderer.as , BUT i didnt understood how does it getting value, from where??
3) I heard from many people saying that Flex developed from Java, Is that correct? If yes, why I didnt found not even a single java file inside Flex Source code?
4) now Curretnly, Apache is owner of Flex, so then why does Flex API still showing as 'Adobe'? (asked this just to know myself)
Sorry, if they're stupid queries!
Waiting for replies!
1) How does my 'rendererFunction' code returns a ItemRenderer at end?
I mean how does ClassFactory returns a ItemRenderer object?
I'm not sure what your really asking here, but I'll try. I believe it happens like this:
1) The DataGroup needs an itemRenderer to display some data
2) The DataGroup checks to see if an itemRendererFunction exists. if it does; it calls the function. The function returns a ClassFactory
3) The ClassFactory is used inside the DataGroup to create a new instance. I would assume that the newInstance() method is called; but I am not reviewing the code to write this.
4) The DataGroup sets the data property on the new renderer instance. I assume it also stores the renderer instance somewhere.
5) The renderer instance is added as a child of the DataGroup
At the end of the day; you'll have to delve into the Flex Framework code to figure out the answers to your questions.
2) Inside DisplayName.mxml code:
The DataGroup will set the data property on the renderer. It relates to an item from the DataGroup's dataProvider.
3) I heard from many people saying that Flex developed from Java, Is
that correct? If yes, why I didnt found not even a single java file
inside Flex Source code?
The Flex compiler is built in Java. The Flex Framework is all ActionScript.
4) now Curretnly, Apache is owner of Flex, so then why does Flex API
still showing as 'Adobe'? (asked this just to know myself)
For backward compatibility reasons primarily. I believe the Apache Flex SDK includes new classes which are not in an Adobe namespace.