The data grid is one of the most used elements in Flex, for displaying collections of data. There are many reasons for this, among which I'd like to mention its flexibility in handling different data and ease of use (basically, all you need to do, is specify a data provider).
In addition to this, the DataGrid object, can handle more advanced operations. For instance, using customized item rendering components, or data editing (and this will be our main focus for this post).
So, how can we edit the data inside a data grid? First, by specifying that the user is allowed to do this, by setting the editable property of the data grid to true. Then, when running the application, all the user has to do is click on the cell that needs to be edited.
Let's consider the following scenario. We use a data grid for editing the data in an array collection, but we want to check if a cell value was actually modified before we save the new data (since it wouldn't make sense to update the current data if no actual values were changed - i.e. the user edited a field, but then reverted it to the previous value). How do we do this?
First by understanding the events that a DataGrid object dispatches, particularly the ITEM_EDIT_END event, since it is dispatched before the old value is replaced. That being said, we know when to determine if an actual change has been made. The only problem remaining is how, specifically how do we compare the old value, with the new one?
We can determine the initial value by using the data grid's itemRenderer property, which is an instance of the component used to display the data and is passed to the event also. To access the data, we still need to determine the field that was edited, and we can do so by using the event's dataField property. Now to access the data, we can use:
event.itemRenderer.data[ event.dataField ];
So now that we have the old value, we need to get the new value. This step is a little easier, since we don't actually need to know the field that was edited, because the data grid contains a TextInput element instance, for editing a cell. We can retrieve its value by using the data grid's itemEditor property which, as mentioned above, is a TextInput instance, so we can use its text property to get the new value:
event.currentTarget.itemEditorInstance.text;
If we assign these values to, let's say, the oldValue and newValue, we can make a simple comparison to determine if indeed the new value is different from the old one.
Romi's Flex corner
luni, 4 iulie 2011
joi, 7 aprilie 2011
IE6 is still hanging in there
If you have been in the web development industry for a few years, chances are you have heard about, got mad at (read "utterly angry"), and fought against browser compatibility issues in Internet Explorer 6. Now don't get me wrong, I don't mean to say anything bad about it (meaning I'm just glad since I don't have to work with it anymore), but this post was inspired by Chris Heilmann's article HTML5 for XP now! and particularly by a link in it: Internet Explorer 6 Countdown.
After checking it out, I must admit I found it a bit odd for Microsoft to "bury" its own baby. I mean, they could have left it silently slip out of the web scene. However, since it reigned for so long, in order to make it go extinct, they actually had to step up and do something about it themselves, rather then just let people upgrade or switch browsers. So, in my opinion that's just like saying "yeah, we made a mistake...".
So, if you haven't ever been forced to resort to hacks, IE-specific stylesheets etc. you can call yourself a lucky web developer. I am curious if there are such developers today, because sometimes I still hear "cross-browser", or "IE issues" and after I don't feel chills running down my spine anymore, the first thing I feel like saying is "Oh, that takes me back...". A few years from now I'm sure people will still remember the name of IE6 (and fear it) even though it will be long gone, and a few years later still my kids will ask "Dad, have you ever heard of IE6? Is it true that most of the development time was used to fix IE6 issues?". My answer will be "Yes, it is true, so be good if you don't ever want to use it for browsing...".
I'm pretty certain IE6 will be a sort of boogie man for future generations of web developers.
After checking it out, I must admit I found it a bit odd for Microsoft to "bury" its own baby. I mean, they could have left it silently slip out of the web scene. However, since it reigned for so long, in order to make it go extinct, they actually had to step up and do something about it themselves, rather then just let people upgrade or switch browsers. So, in my opinion that's just like saying "yeah, we made a mistake...".
So, if you haven't ever been forced to resort to hacks, IE-specific stylesheets etc. you can call yourself a lucky web developer. I am curious if there are such developers today, because sometimes I still hear "cross-browser", or "IE issues" and after I don't feel chills running down my spine anymore, the first thing I feel like saying is "Oh, that takes me back...". A few years from now I'm sure people will still remember the name of IE6 (and fear it) even though it will be long gone, and a few years later still my kids will ask "Dad, have you ever heard of IE6? Is it true that most of the development time was used to fix IE6 issues?". My answer will be "Yes, it is true, so be good if you don't ever want to use it for browsing...".
I'm pretty certain IE6 will be a sort of boogie man for future generations of web developers.
marți, 5 aprilie 2011
Be nice to developers
Lately I have been reading Scott Rosenberg's book, Dreaming in code and besides all the interesting ideas and stories therein, one quote in particular stuck in my mind "Our civilization runs on software".
If you think about it, every item we use on a day to day basis, relies on software to function. If that's true, then it's safe to say that software developers make the world go round. This may be one way to explain why more and more people are getting into the software industry (this includes developers, testers, managers, marketers, distributors - you name it - of course, not necessarily in that order).
Which brings me to my point. A friend of mine once told me an interesting story. He was in a restaurant abroad and since he is a very good cook, he wasn't happy with the way the food he ordered was prepared. Rather than complain to the waiter, he left his food and went away. Intrigued by this I asked him what was his reason for doing so. He told me that it is never wise to argue with people who prepare or serve your food... and you can imagine why.
I have to admit it made perfect sense to me. Besides, if one person doesn't like something (in this case, the way some food is prepared), that doesn't mean there isn't someone who actually loves it that way (except for a few cases in which the food is very bad prepared). And if that's true for food, which is something we need on a daily basis, why wouldn't it be also true for software?
So in closing, if you don't mess with people who prepare and serve your food, you certainly don't want to mess with people who code your software. Remember, the people who cook your food, rely on software to get the recipes right.
Don't mess with us, we control every aspect of your modern life...
If you think about it, every item we use on a day to day basis, relies on software to function. If that's true, then it's safe to say that software developers make the world go round. This may be one way to explain why more and more people are getting into the software industry (this includes developers, testers, managers, marketers, distributors - you name it - of course, not necessarily in that order).
Which brings me to my point. A friend of mine once told me an interesting story. He was in a restaurant abroad and since he is a very good cook, he wasn't happy with the way the food he ordered was prepared. Rather than complain to the waiter, he left his food and went away. Intrigued by this I asked him what was his reason for doing so. He told me that it is never wise to argue with people who prepare or serve your food... and you can imagine why.
I have to admit it made perfect sense to me. Besides, if one person doesn't like something (in this case, the way some food is prepared), that doesn't mean there isn't someone who actually loves it that way (except for a few cases in which the food is very bad prepared). And if that's true for food, which is something we need on a daily basis, why wouldn't it be also true for software?
So in closing, if you don't mess with people who prepare and serve your food, you certainly don't want to mess with people who code your software. Remember, the people who cook your food, rely on software to get the recipes right.
Don't mess with us, we control every aspect of your modern life...
miercuri, 16 martie 2011
Flex 4 states changes
Recently I had the task of reimplementing a tool tip component, using the new Flex 4 state features. The component had to states, default and expanded. The latter had just a few additional information than the first one.
Traditionally, states were meant to implement the look and feel of a component, totally independent of each other, so it was frequent to have repeating content between states. But all that has changed in Flex 4.
After reading a very helpful article about the recent changes, which you can find here, I was pleasantly surprised to see that state content was no longer segmented (in a sense that the content for a state, is completely separated for the other states) but rather, each element in the component can be assigned to a specific state. This way the states serve merely a design/functionality purpose, and the elements themselves can be included or excluded into or from a specific state. That way, no content is repeated.
Here is a quick example of this concept, a component consisting of a text (default state) and a button (expanded state):
First, the Flex 3 implementation:
<mx:states>
<mx:State name="default">
<mx:AddChild>
<mx:TextInput id="myTextInput" />
You can see how the state layouts are completely independent of each other. Now let's take a look at the new way of defining states:
<s:states>
<s:State name="default" />
<s:State name="expanded" />
</s:states>
Traditionally, states were meant to implement the look and feel of a component, totally independent of each other, so it was frequent to have repeating content between states. But all that has changed in Flex 4.
After reading a very helpful article about the recent changes, which you can find here, I was pleasantly surprised to see that state content was no longer segmented (in a sense that the content for a state, is completely separated for the other states) but rather, each element in the component can be assigned to a specific state. This way the states serve merely a design/functionality purpose, and the elements themselves can be included or excluded into or from a specific state. That way, no content is repeated.
Here is a quick example of this concept, a component consisting of a text (default state) and a button (expanded state):
First, the Flex 3 implementation:
<mx:states>
<mx:State name="default">
<mx:AddChild>
<mx:TextInput id="myTextInput" />
</mx:AddChild>
</mx:State>
<mx:State name="expanded">
<mx:AddChild>
<mx:TextInput id="myTextInput" />
<mx:Button id="myButton" />
</mx:AddChild>
</mx:State>
</mx:states>
You can see how the state layouts are completely independent of each other. Now let's take a look at the new way of defining states:
<s:states>
<s:State name="default" />
<s:State name="expanded" />
</s:states>
<s:VGroup>
<s:TextInput id="myTextInput" />
<s:Button id="myButton" includeIn="expanded" />
</s:VGroup>
Quite a difference. An equivalent implementation would be to use excludeFrom="default" instead of includeIn="expanded".
For more information regarding Flex 4 states changes and examples, read Adobe's Enhanced States Syntax article.
vineri, 25 februarie 2011
My social media platform
We are all using social media nowadays. Some for collaboration as opposed to using email, others for finding out the latest news. However, must of us use it to share stuff we find interesting.
I use it too, and mainly for the stuff I described above. I need to keep in touch with business contacts (yes yes, I do use email as well...), sometimes I want to check out what's been happening in areas I consider interesting, but mostly I like to share stuff, of course, not just my own :)
So I present to you my own social media platform:
There we have it! The cream of the crop in social media!
I use it too, and mainly for the stuff I described above. I need to keep in touch with business contacts (yes yes, I do use email as well...), sometimes I want to check out what's been happening in areas I consider interesting, but mostly I like to share stuff, of course, not just my own :)
So I present to you my own social media platform:
There we have it! The cream of the crop in social media!
luni, 21 februarie 2011
TileBox - background image container component
Recently I had to implement a layout, which had in its header's background an image that could be tiled to create a rather nice looking effect. One problem in Flex is that creating containers that have a tiling background image is not so simple as in CSS (i.e. specify background-image and background-repeat properties ). To accomplish this, you would need to extend an existing component and then rewrite the rendering method.
Taking into account the fact that I slice a lot layouts, it made sense to make a component that could be easily added to any project, that needs a container with a tiling background image. I named it TileBox because you can basically use it as a standard (H/V)Box container (well, almost, you'll see...).
Before we take a look at the code, let's see a quick demo: http://romualdhalasz.com/projects/tilebox/
The way to use it in a Flex application goes something like this (I'll use MXML for simplicity):
1. Create a TileBox object (notice the namespace) with a text object as its child
<tilebox:TileBox width="100%" height="100%">
<mx:Text text="One line" />
</tilebox:TileBox>
2. Set the source property, which is the equivalent property of an Image object's:
Taking into account the fact that I slice a lot layouts, it made sense to make a component that could be easily added to any project, that needs a container with a tiling background image. I named it TileBox because you can basically use it as a standard (H/V)Box container (well, almost, you'll see...).
Before we take a look at the code, let's see a quick demo: http://romualdhalasz.com/projects/tilebox/
The way to use it in a Flex application goes something like this (I'll use MXML for simplicity):
1. Create a TileBox object (notice the namespace) with a text object as its child
<tilebox:TileBox width="100%" height="100%">
<mx:Text text="One line" />
</tilebox:TileBox>
2. Set the source property, which is the equivalent property of an Image object's:
<tilebox:TileBox width="100%"
height="100%"
source="@Embed(source='assets/bg-image.jpg')">
<mx:Text text="One line" />
</tilebox:TileBox>
Voila! Now we have a container that has a tiling image as it's background. But it's still not quite enough. What if we want to tile the image only on a specific axis? This is a situation we find ourselves in more often that the one described above. Not to worry, specifying the repeat axis is as is easy as setting the background-repeat property in CSS:
<tilebox:TileBox width="100%"
height="100%"
source="@Embed(source='assets/autumn-leaf-tile.jpg')"
backgroundRepeat="repeat-x">
<mx:Text text="One line" />
</tilebox:TileBox>
The backgroundRepeat property's default value is "all", meaning both axes. Use repeat-y if you want to tile the background only on the vertical axis.
So far so good! But now we can tile horizontally only on top of the container, and vertically on the left side. What if we want to tile an image horizontally, on the bottom of the container, or vertically on the right side? We might have a problem, if we didn't have the backgroundPosition property:
<tilebox:TileBox width="100%"
height="100%"
source="@Embed(source='assets/autumn-leaf-tile.jpg')"
backgroundRepeat="repeat-x"
backgroundPosition="top">
<mx:Text text="One line" />
</tilebox:TileBox>
This property work exactly like you would expect it to: it can take the usual values - "bottom", "left", "right" and "top".
You can see the demo here: http://romualdhalasz.com/projects/tilebox/
Just use the combo menus on top to modify the repeat or position property to see different uses.
If you want to use the component in your own projects, just add TileBox.swc file to your libs. You can download it here: http://romualdhalasz.com/projects/tilebox/TileBox.swc
For any suggestions on improving this little component, drop a line and I'll see what can be done!
joi, 17 februarie 2011
How do we measure good code?
A question with no simple answer, because the notion of good code varies from coder to coder, from team to team and from project to project. Also, there are many criteria for determining the quality of written code. Let me give you a few examples: actual code size, number of units, time needed to write, memory usage, request handling, practices employed etc.
As you can see, there are a myriad of criteria which play a significant role when considering the "overall goodness" of your written code and furthermore, if attempting to evaluate your code using these guidelines, you will quickly find out that the result is relative to each project, at best.
This was a concept that stuck in my head for some time now, mainly because I'm always interested in improving the quality of the projects I'm involved in, by writing improved code. I'm talking about both professional and personal projects.
First, let's consider the fact that in order to classify the code written, we need to have a solid basis for evaluating a task relative to the project it belongs to, because the same task can have varying difficulty in different projects. And here is the core of the issue. Normally, adding the feature (i.e. doing a task) to an existing project, should have the same difficulty regardless of the overall project complexity. You may not fully agree with this concept, but if you disregard project-specific data structures and keep in mind only the flow or functionality, then it might make more sense.
This is precisely why I tend to believe that "code goodness" can be determined by the amount of changes (to the already existing code) needed in order to complete the task. So, we cannot determine how well some code was written, until we see how flexible it is, in the sense that it must be flexible enough so we can add new things, without altering it. Now, that might sound weird, counter-intuitive, but it makes sense if you think about it.
Here's an example. Let's say we are implementing an application for managing songs (add / edit / delete). It might be simple enough, but there are many ways to go about it, so let me give you a quick example: We have an object that manages songs by building queries based on input data and then executes them to update the records. Now, we need to extend the functionality a bit, and add the possibility to manage videos in the same way. You can see the fact that although the data structure might have changed, the functionality itself did not. So, if we were to change the way songs are managed, just so we can manage videos as well, then that would be a sign that the code we have previously written, was not flexible enough. In more technical terms, the model was tightly coupled with the business logic. Therefore, the controller does not allow new functionality to be added without altering its previous code. We could also clone the functionality for the video manager, but it still would be far from perfect since we have two objects that exhibit the same behavior.
On the other hand, if our controller was written in such a way that it can manage varying data structures, then we know it is good. A more flexible example would be to separate the database operations manager from the input parser. The way to do that would be to have some object for gathering the data, then another for building queries based on the current data structure, and finally, one to manager the database connection and execute a query.
Now that's a lot better! We can add a whole lot of new data types, like books for instance and we can focus solely on the code needed to handle books, not songs or videos.
In conclusion, we can only determine how good code a segment of code is, after we have written it, and used it, by determining the amount of code we need to change in order to implement new requirements. Of course, this means a smaller value corresponds to a higher rating.
Also, it is generally a good idea, when designing the architecture of a project, to take into account things that resemble the requirements, but haven't been explicitly requested, this way you can help improve the flexibility of your code dramatically, and in time, it will become like a reflex. The direct result of this habit is that the code you write will be more abstracted, and therefore handle additions without too much (and later hopefully none) code changes.
As you can see, there are a myriad of criteria which play a significant role when considering the "overall goodness" of your written code and furthermore, if attempting to evaluate your code using these guidelines, you will quickly find out that the result is relative to each project, at best.
This was a concept that stuck in my head for some time now, mainly because I'm always interested in improving the quality of the projects I'm involved in, by writing improved code. I'm talking about both professional and personal projects.
First, let's consider the fact that in order to classify the code written, we need to have a solid basis for evaluating a task relative to the project it belongs to, because the same task can have varying difficulty in different projects. And here is the core of the issue. Normally, adding the feature (i.e. doing a task) to an existing project, should have the same difficulty regardless of the overall project complexity. You may not fully agree with this concept, but if you disregard project-specific data structures and keep in mind only the flow or functionality, then it might make more sense.
This is precisely why I tend to believe that "code goodness" can be determined by the amount of changes (to the already existing code) needed in order to complete the task. So, we cannot determine how well some code was written, until we see how flexible it is, in the sense that it must be flexible enough so we can add new things, without altering it. Now, that might sound weird, counter-intuitive, but it makes sense if you think about it.
Here's an example. Let's say we are implementing an application for managing songs (add / edit / delete). It might be simple enough, but there are many ways to go about it, so let me give you a quick example: We have an object that manages songs by building queries based on input data and then executes them to update the records. Now, we need to extend the functionality a bit, and add the possibility to manage videos in the same way. You can see the fact that although the data structure might have changed, the functionality itself did not. So, if we were to change the way songs are managed, just so we can manage videos as well, then that would be a sign that the code we have previously written, was not flexible enough. In more technical terms, the model was tightly coupled with the business logic. Therefore, the controller does not allow new functionality to be added without altering its previous code. We could also clone the functionality for the video manager, but it still would be far from perfect since we have two objects that exhibit the same behavior.
On the other hand, if our controller was written in such a way that it can manage varying data structures, then we know it is good. A more flexible example would be to separate the database operations manager from the input parser. The way to do that would be to have some object for gathering the data, then another for building queries based on the current data structure, and finally, one to manager the database connection and execute a query.
Now that's a lot better! We can add a whole lot of new data types, like books for instance and we can focus solely on the code needed to handle books, not songs or videos.
In conclusion, we can only determine how good code a segment of code is, after we have written it, and used it, by determining the amount of code we need to change in order to implement new requirements. Of course, this means a smaller value corresponds to a higher rating.
Also, it is generally a good idea, when designing the architecture of a project, to take into account things that resemble the requirements, but haven't been explicitly requested, this way you can help improve the flexibility of your code dramatically, and in time, it will become like a reflex. The direct result of this habit is that the code you write will be more abstracted, and therefore handle additions without too much (and later hopefully none) code changes.
Abonați-vă la:
Postări (Atom)
