Titanium JIRA Archive
Alloy (ALOY)

[ALOY-1071] Can't dynamically override backgroundColor of a view

GitHub Issuen/a
TypeNew Feature
PriorityMedium
StatusClosed
ResolutionInvalid
Resolution Date2014-07-23T16:49:28.000+0000
Affected Version/sn/a
Fix Version/sn/a
ComponentsStyling
Labelsdynamic, style, touch
ReporterMatteo Landi
AssigneeUnknown
Created2014-06-09T09:28:54.000+0000
Updated2018-03-07T22:28:29.000+0000

Description

I am playing with touch start/end/cancel events to change view colors dynamically, and it seems like I can't override the background color of a view if a background color for that view has been previously defined without the aid of a _style class_. Take a look at this simple example:
<Alloy>
    <Window id="index">
        <View id="view" class="view"
            onTouchstart="change_view_background"
            onTouchend="reset_view_background"
            onTouchcancel="reset_view_background" />
    </Window>
</Alloy>
$.index.open();


function change_view_background(e) {
    console.log('change view background');
    $.addClass($.view, 'clicked');
}

function reset_view_background(e) {
    console.log('reset view background');
    $.removeClass($.view, 'clicked');
}
"#view": {
    backgroundColor: "blue",
}

".view": {
}

".clicked": {
    backgroundColor: "green",
}
When I click the view, instead of watching its background color change from blue to green, nothing happens. If on the other hand I move the backgroundColor definition out of the #view block and into the .view one:
"#view": {
}

".view": {
    backgroundColor: "blue",
}

".clicked": {
    backgroundColor: "green",
}
I can see the background color change from blue to green. Why is that happening? And why after the $.removeClass the background color happens to be transparent and not blue? Am I doing something wrong?

Comments

  1. Shuo Liang 2014-06-10

    Hi, First of all, in css style, The "#" is stand for id, "." is stand for class. You added ".click" class to class ".view" in index.js, but in tss file, the original colour is defined by id "#view", not class ".view". Even id and class define the same place in you code, but class is not unique, so in css definition of id and class could cause different behaviour. Secondly, after "$.removeClass" in you code, remove ".click"class, but it doesn't means it will go back to ".view" class. then there will be no any class defined for the view. That is why he background colour happens to be transparent(default black). In your case, you might add on line
    $.addClass($.view, 'view');
    after
    $.removeClass($.view, 'clicked');
    Hope it will help you. Regards, Shuo
  2. Matteo Landi 2014-06-10

    {quote} First of all, in css style, The "#" is stand for id, "." is stand for class. You added ".click" class to class ".view" in index.js, but in tss file, the original colour is defined by id "#view", not class ".view". {quote} Your are right about #/.-notation, but with $.addClass($.view, 'clicked') I am just trying to change the view having id 'view' -- the one with the 'blue' background. {quote} Even id and class define the same place in you code, but class is not unique, so in css definition of id and class could cause different behaviour. {quote} As far as I know, it shouldn't be a problem to have an object and a style class with the same name, but maybe am a little bit optimistic here.. {quote} Secondly, after "$.removeClass" in you code, remove ".click"class, but it doesn't means it will go back to ".view" class. then there will be no any class defined for the view. That is why he background colour happens to be transparent(default black) {quote} Well, I haven't double-checked that but the view should be tracking all the style classes still holding after the $.removeClass, so it shouldn't be difficult for the UI engine to re-evaluate them -- rather than requiring the developer to manually re-apply all of them. Ciao, Matteo
  3. Shuo Liang 2014-06-11

    Hi, There is some miss understanding in last comment, here is the correct comment. 1.When you use id and class together, that is not a problem. But you have to be careful with them. The class is a global property, and id is a local property. So during the page or window loading up, class defined style will display first, then the id's. Think it as id has higher priority. So no matter how you add class with new background colour, once you define colour for #view (id ref), the page will always display the id's colour style. That is why colour didn't change at first place. 2.For your case, you should enable the autoStyle, that is, set the autoStyle attribute of the component to true in the XML markup. Like
       <Alloy autoStyle="true">
       
    Ref: http://docs.appcelerator.com/platform/latest/#!/guide/Dynamic_Styles Regards Shuo
  4. Mauro Parra-Miranda 2014-06-24

    Hello, why add a class in the controller? You can just do $view.backgroundColor = 'change'; Best, Mauro
  5. Matteo Landi 2014-06-28

    @Shuo: thank you so much for the comment. I was not aware of the id/style-class precendence thing, and neither of the View's autoStyle property (I have just tried i and worked like a charm). I think the ticket could be closed now. @Mauro: in general, changing the view is definitely more flexible than changing all the properties related to the effect you wanted to achieve. In this case I could have changed the backgroundColor property only, but for the completeness of the example I went for adding/removing style classes. Ciao, Matteo
  6. Mauro Parra-Miranda 2014-06-29

    Hello [~landimatte]! Here we can go in two different directions, and let me know what do you think: - [NotABug] Once you compiled your Alloy code, it will be compiled into Classic code, and then native code. Therefore, changing dynamically the class won't work (you can't dynamically reload the new tss nor reload already processed classic code). - [New Feature] You want this to happen. But, in order to do so, you will need a kind of living system catching those changes to a class will be reflected at running time. Let me know how you want to process this. Thanks!
  7. Matteo Landi 2014-06-29

    Hello Mauro, It's true, am not able to dynamically override the style of a view with a class-style because of the id/class precendence story, but a very simple workaround is just to use classes as much as possible and then use $.addClass $.removeClass and autoStyle="true". The question is: can the code be changed so that style-classes take precedence over every other style definition (i.e. styles defined by #id). I don't have a strong opinion on it, so am open to comments. Ciao, Matteo
  8. Mauro Parra-Miranda 2014-07-04

    Original reporter: [~landimatte]
  9. Tim Poulsen 2014-07-23

    I'm going to close this as invalid because the behavior is documented and because there are ways to accomplish your goals. From the docs page linked to in the comments: "Properties defined inline in the markup and TSS id styles still take precedence over class styles." Because the style rules are evaluated at build time, it's not a simple change to implement the functionality you describe. We will likely be reworking the styling features in upcoming Alloy releases (to correspond with Ti.Next). Those changes will hopefully lead to a more dynamic system that meets your expectations better.
  10. Matteo Landi 2014-07-23

    Sounds good to me. Thank you for the support.
  11. Eric Merriman 2018-03-07

    Closing as invalid. If this is incorrect, please reopen.

JSON Source