Aurelia `#dynamicOptions` mixed with `#bindable`s - aurelia

I am developing using aureliajs. By now I am working on a custom attribute which has marked to have dynamic options. For example consider following code:
import {dynamicOptions, inject} from 'aurelia-framework';
#dynamicOptions
#inject(Element)
export class SquareCustomAttribute {
constructor(element){
this.element = element;
}
propertyChanged(name, newValue, oldValue){
switch(name){
case 'fill':
this.element.style.backgroundColor = newValue;
break;
case 'size':
this.element.style.width = this.element.style.height = `${newValue}px`;
break;
default:
this.element.style[name] = newValue;
break;
}
}
}
now for example consider that I want to give the property fill, defaultBindingMode of twoWay, so I will try to add the #bindable property in class. So the code will change to this:
import {dynamicOptions, inject} from 'aurelia-framework';
#dynamicOptions
#inject(Element)
export class SquareCustomAttribute {
#bindable fill;
constructor(element){
this.element = element;
}
propertyChanged(name, newValue, oldValue){
switch(name){
case 'fill':
this.element.style.backgroundColor = newValue;
break;
case 'size':
this.element.style.width = this.element.style.height = `${newValue}px`;
break;
default:
this.element.style[name] = newValue;
break;
}
}
}
And binding stops working.
So, the first question is how to set defaultBindingMode for dynamicOptions?
And another little question. As aurelia.io says, Binding to a dynamic options attribute works exactly the same as binding to an options attribute in the DOM.. According to this sentence, I expect to bind dynamic options dash seperated and retrieve the in camel case on optionsChanged method. But dash seperated options bound from view, receives dash separated and camels, camels. Is this correct according to referenced sentence from aurelia.io?

Thanks to #bigopon, this issue is being followed up in this issue and I think any additional comment on that will be beneficial before making changes on aurelia-framework.

Related

How to Remove this Arrow or Image From IOS Listview in Xamarin forms

when i write a listview in xamarin forms this icon is auto added to IOS and this is not present in Android
i tried removing this using custom renderer by rendering viewrenderer but this this view renderer never gets call
here is the code which i used for custom renderering
[assembly: ExportRenderer(typeof(ViewCell),
typeof(StandardViewCellRenderer))]
namespace Sample.iOS.Renderers.RevisedRenderer
{
public class StandardViewCellRenderer : ViewCellRenderer
{
public override UIKit.UITableViewCell GetCell(Cell item,
UIKit.UITableViewCell reusableCell, UIKit.UITableView tv)
{
var cell = base.GetCell(item, reusableCell, tv);
switch (item.StyleId)
{
case "none":
cell.Accessory = UIKit.UITableViewCellAccessory.None;
break;
case "checkmark":
cell.Accessory = UIKit.UITableViewCellAccessory.Checkmark;
break;
case "detail-button":
cell.Accessory =
UIKit.UITableViewCellAccessory.DetailButton;
break;
case "detail-disclosure-button":
cell.Accessory =
UIKit.UITableViewCellAccessory.DetailDisclosureButton;
break;
case "disclosure":
default:
cell.Accessory =
UIKit.UITableViewCellAccessory.DisclosureIndicator;
break;
}
return cell;
}
}
}
let me know what need to be modified or add to make it work
remove your switch, and leave the code like this:
var cell = base.GetCell (item, reusableCell, tv);
cell .Accessory = UITableViewCellAccessory.DisclosureIndicator;
You can get more details at:
https://forums.xamarin.com/discussion/88286/xamarin-viewcell-how-to-turn-off-right-arrow-meant-for-touch-action
Cause:
i tried removing this using custom renderer by rendering viewrenderer
but this this view renderer never gets call
The view renderer did get call in your project while the code inside Switch statement never executed, because item.StyleId is always null. You can add a breakpoint to check it.
Solution:
If you want to remove the arrow, just set cell.Accessory = UIKit.UITableViewCellAccessory.None; will work.
class StandardViewCellRenderer : ViewCellRenderer
{
public override UIKit.UITableViewCell GetCell(Cell item,
UIKit.UITableViewCell reusableCell, UIKit.UITableView tv)
{
var cell = base.GetCell(item, reusableCell, tv);
Console.WriteLine(item.StyleId);
cell.Accessory = UIKit.UITableViewCellAccessory.None;
// switch (item.StyleId)
// {
// case "none":
// cell.Accessory = UIKit.UITableViewCellAccessory.None;
// break;
// case "checkmark":
// cell.Accessory = UIKit.UITableViewCellAccessory.Checkmark;
// break;
// case "detail-button":
// cell.Accessory =
// UIKit.UITableViewCellAccessory.DetailButton;
// break;
// case "detail-disclosure-button":
// cell.Accessory =
//UIKit.UITableViewCellAccessory.DetailDisclosureButton;
// break;
// case "disclosure":
// default:
// cell.Accessory =
// UIKit.UITableViewCellAccessory.DisclosureIndicator;
// break;
// }
return cell;
}
}
If you want to show cells with different cell.Accessory style, you can create a custom property instead of using StyleId.
I also uploaded a demo here.

Ionic2 dynamic navigation

I'm building an app where the data comes from the server. The menu is dynamic, and the server can send different menus depending on the user profile. I will never know what will be the component/page, that the menu item will have, I just need to have that component/page available.
The main problem is that I need to do a lot of components/pages imports and I do not want to that in every component/page.
I created a service, where all the imports are made and a method exists to return the correct component, so the navController could navigate.
import { Injectable } from '#angular/core';
//Import navigation pages
import { NotificationsPage } from "./../pages/notifications/notifications";
import { ClubPage } from "./../pages/club/club";
import { ActivitiesPage } from "./../pages/activities/activities";
import { NewsPage } from "./../pages/news/news";
import { CalendarPage } from "./../pages/calendar/calendar";
import { NewsletterPage } from "./../pages/newsletter/newsletter";
import { SettingsPage } from "./../pages/settings/settings";
import { FavoritesPage } from "./../pages/favorites/favorites";
import { SubmenuPage } from "./../pages/submenu/submenu";
import { ContentDetailsPage } from "./../pages/contentdetails/contentdetails";
#Injectable()
export class ViewNavigatorService
{
public NOTIFICATIONS:string = "notifications";
public CLUB:string = "club";
public ACTIVITIES:string = "activities";
public NEWS:string = "news";
public CALENDAR:string = "calendar";
public NEWSLETTER:string = "newsletter";
public SETTINGS:string = "settings";
public FAVORITS:string = "favorits";
public SUBMENU:string = "submenu";
public CONTENT_DETAILS:string = "content-details";
public GetComponent(page:string, data?:any):any
{
let Component = null;
switch (page)
{
case this.NOTIFICATIONS: Component = NotificationsPage; break;
case this.CLUB: Component = ClubPage; break;
case this.ACTIVITIES: Component = ActivitiesPage; break;
case this.NEWS: Component = NewsPage; break;
case this.CALENDAR: Component = CalendarPage; break;
case this.NEWSLETTER: Component = NewsletterPage; break;
case this.SETTINGS: Component = SettingsPage; break;
case this.FAVORITS: Component = FavoritesPage; break;
case this.SUBMENU: Component = SubmenuPage; break;
case this.CONTENT_DETAILS: Component = ContentDetailsPage; break;
default: Component = null; break;
}
return Component;
}
}
If I only inject the service in a parent page it works, but if I also inject the service in a child page, I get this error:
Can't resolve all parameters for SubmenuPage: (NavController, NavParams, PopoverController, AlertController, ModalController, ?).
The ? should be the "ViewNavigatorService".
Why this error happens?
Is there a better way to do this? What are you using when your app uses dynamic navigation?

Dynamic view creation

I'm trying to get a simple dynamic view working the simplest possible way.
import {inject, noView, ViewCompiler, ViewSlot} from 'aurelia-framework';
#noView
#inject(ViewCompiler, ViewSlot)
export class ButtonVM{
constructor(vc, vs){
this.viewCompiler = vc;
this.viewSlot = vs;
var viewFactory = this.viewCompiler.compile('<button>Some button</button>');
but apparantly I'm missing something, the view factory should be able to create a view and then it should be added to a viewslot?
What am I missing in the above code?
I should mention that I tried to follow Rob's comments in this thread:
https://github.com/aurelia/templating/issues/35
See the updated post by Rob in the same thread.
import {inject, noView, ViewCompiler, ViewSlot, Container, ViewResources} from 'aurelia-framework';
#noView
#inject(ViewCompiler, ViewSlot, Container, ViewResources)
export class Test {
constructor(vc, vs, container, resources){
this.viewCompiler = vc;
this.viewSlot = vs;
var viewFactory = this.viewCompiler.compile('<button>${title}</button>', resources);
var bindingContext = { title:'Click Me'};
var view = viewFactory.create(container, bindingContext);
this.viewSlot.add(view);
this.viewSlot.attached();
}
}
Late for an answer but this can be easily achieved by using getViewStartegy method provided by aurelia.
export class Test {
constructor(vc, vs, container, resources){
}
getViewStrategy() {
return new InlineViewStrategy('<button>${title}</button>');
}
}

How can I handle the element locator selection type(xpath or tag or id or class) changing frequently using Selenium?

In my application during releases, I'm forced to change id to xpath or class name or tag. So I can't use any of the element selection methods like driver.findElement(By.id()).
In the next build I might have to use driver.findElement(By.xpath()) OR driver.findElement(By.name()) for the same element location. This means I will have to visit each and every class file I have written and modify By.id() to the respective selector.
Is there any way to avoid this by parametrising or some other way to resolve this issue?
Thanks in advance.
Had similar issue so came up with this generic method
public WebElement getElement(Identifier identifier, String expression) {
By byElement = null;
switch (identifier) {
case xpath: {
byElement = By.xpath(expression);
break;
}
case id: {
byElement = By.id(expression);
break;
}
case name: {
byElement = By.name(expression);
break;
}
case classname: {
byElement = By.className(expression);
break;
}
case linktext: {
byElement = By.linkText(expression);
break;
}
case paritallinktext: {
byElement = By.partialLinkText(expression);
break;
}
case tagname: {
byElement = By.tagName(expression);
break;
}
}
WebElement element = driver.findElement(byElement);
return element;
}
public static enum Identifier {
xpath, id, name, classname, paritallinktext, linktext, tagname
};
You can also use properties file to store values. Like
# login
login.username.identifier=xpath
login.username.expression=//input[#id='userNameText']
and in Java you can write
SeleniumUtil.getElement(prop.getProperty("login.username.identifier"), prop.getProperty("login.username.expression")).click();
So you will not need to change any Java code
You can also make use of key=value in your locators as a good practice which was seen in Selenium 1.0 and accordingly the selector will be selected.
So you can have a common getByLocator method that returns you with the By class object, example code
public By getByLocator(String locator) {
By by = null;
if (locator.startsWith("class=")) {
by = By.className(locator.replace("class=", "").trim());
} else if (locator.startsWith("css=")) {
by = By.cssSelector(locator.replace("css=","").trim());
} else if (locator.startsWith("link=")) {
by = By.linkText(locator.replace("link=", "").trim());
} else if (locator.startsWith("//") or locator.startsWith("/")) {
by = By.xpath(locator);
} else if (locator.startsWith("id=")) {
by = By.id(locator.replace("id=", ""));
} else {
by = By.name(locator.replace("name=", ""));
}
return by;
}
Here I made use of link=, css=, id= as some of factors to identify the locator type and accordingly I got the By locator object.
The usage of this would be something like below
List<WebElement> element = driver.findElements(getByLocator("css= input[type=input]"));
You have to work on your framework. Make it more generic. My code handles the problem. I have used key and value concept. In my .properties file, I have defind the object like
Test_login_user=id||username
Test_login_pass=className||passwd
after that my code get the value and spits it from ||. Here I have mention the type of locator if its BY id then id||username etc.
public By extractWebElement(String keyobject){
if(keyobject.startsWith("name_")){
currentWebElement = By.name(actualLocator);
}else if(keyobject.startsWith("xpath_")){
currentWebElement =By.xpath(actualLocator);
}else if(keyobject.startsWith("linkText_")){
currentWebElement =By.linkText(actualLocator);
}else if(keyobject.startsWith("id_")){
currentWebElement =By.id(actualLocator);
}else if(keyobject.startsWith("cssSelector_")){
currentWebElement =By.cssSelector(actualLocator);
}else if(keyobject.startsWith("tagName_")){
currentWebElement =By.tagName(actualLocator);
}
return currentWebElement;
}
public String extractActualLocator(String locatorInSheet ){
int underScoreIndex = locatorInSheet.indexOf('_');
return locatorInSheet.substring(underScoreIndex+1);
}
Now actual locator is in the "currentWebElement", we can use this in our methods. See how my keywords are written
public String enterTextt(By object,String data){
APP_LOGS.debug("Writing in text box");
try{
***driver.findElement(object).sendKeys(data);***
}catch(Exception e){
return Constants.KEYWORD_FAIL+" Unable to write "+e.getMessage();
}
return Constants.KEYWORD_PASS;
}

Using Aurelia, how to set a default value for a custom attribute

view
<template>
<div single-value-attrib="${color}"></div>
<div single-value-attrib.bind="color"></div>
<input type="text" value.bind="color" />
</template>
view-model
export class SingleValueAttribCustomAttribute {
static inject = [Element];
color = 'orange';
constructor(element) {
this.element = element;
this.element.style.width = this.element.style.height = '100px';
}
bind() {
this.element.style.backgroundColor = this.value;
}
valueChanged(newValue, oldValue) {
this.element.style.backgroundColor = newValue;
}
}
I was expecting that color='orange'; in the viewModel would map to color on the view thus setting the default color as orange. Changing the color in the input box works as expected. I know you can just set this.value to a color as your default but I just thought that the binding would work the same way as in the skeleton-nav where the input boxes have default values for firstName and lastName
First, note that this.color isn't used anywhere in the code viewmodel, so setting it really doesn't do anything in the code as it exists.
After some playing around, I've determined that your best bet in this specific situation, is going to be to set the background color in the constructor and get rid of the bind function. I've create a gist.run here: https://gist.run/?id=a15e0305f082f6ef080364caff2a1ec1
Here is the VM for the custom attribute:
export class SingleValueAttribCustomAttribute {
static inject = [Element];
defaultColor = 'orange';
constructor(element) {
this.element = element;
this.element.style.width = this.element.style.height = '100px';
this.element.style.backgroundColor = this.defaultColor;
}
valueChanged(color) {
if(color.trim() !== '') {
this.element.style.backgroundColor = color;
}
}
}
You may want to remove the the check for empty string on color in valueChanged, depending on your use-case.