How do I handle click event in Spark List control in Flex 4 - list

I have a s:List component. I want to handle a click event to know what list item is selected. I don't see Click event in s:List. Any workarounds?
Thanks.

I know I'm late to the party here, but the simplest way to get the selected node from list in a click event is to use the currentTarget property.
function myClickHandler(event:MouseEvent):void{
Alert.show("My Var: " + event.currentTarget.selectedItem.myVar);
}
<s:List ... click="myClickHandler(event);">
...
</s:List>
see:
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7cdb.html

You can use the IndexChangeEvent.CHANGE on List
http://docs.huihoo.com/flex/4/spark/events/IndexChangeEvent.html
Package spark.events
Class public class IndexChangeEvent
Inheritance IndexChangeEvent Event Object
Language Version: ActionScript 3.0
Product Version: Flex 4
Runtime Versions: Flash Player 10, AIR 1.5
The IndexChangeEvent class represents events that are dispatched when an index changes in a Spark component.
See also
spark.components.supportClasses.ListBase
spark.components.List
spark.components.ButtonBar

I figured how to do this. Thought I would share so that it helps others like me:
<s:List id="taskList" creationComplete="taskList.addEventListener('listClickEvent',handleListClick);" width="100%" height="80%" labelField="description" dataProvider="{todoList}"
useHandCursor="true">
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer click="handleClick(event)">
<fx:Script>
<![CDATA[
import ListClickEvent;
import flash.events.MouseEvent;
import mx.controls.Alert;
private function handleClick(me:MouseEvent):void
{
var listClickEvent:ListClickEvent = new ListClickEvent("listClickEvent");
listClickEvent.index = itemIndex;
owner.dispatchEvent(listClickEvent);
}
]]>
</fx:Script>
<s:Label text="{data.description}" top="5" bottom="5" right="3" left="3"/>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>

Another way:
<s:List id="myid"
dataProvider="{listDP}"
width="100%"
height="100%"/>
on application creation complete:
myid.addEventListener(MouseEvent.CLICK,clickHandler);
Handler:
private function clickHandler(event:MouseEvent):void
{
if(myid.selectedIndex>=0)
{
...
}
myid.selectedIndex=-1;//to detect click on same item
}

Thanks guys,
Just make sure your List has its id variable set. Then you call in your click handler function like this:
private function listClickHandler(event:IndexChangeEvent) {
if(myListsID.seletectedIndex == 0){
navigator.pushView(whateverViewyouwant)
} else if(myListsID.selectedIndex ==1){
navigator.pushView(changetoanotherview)
} else if(myListsID.selectedIndex == 2){
navigator.pushView(mobileViewsareEasy)
} else if(myListsID.selectedIndex == 3){
navigator.pushView(wowSomanyViews)
}
}
The variable that goes into the pushView function corresponds to the mxml file name for the view you want to load

That is farrrr too complex here is a better way:
<s:List id="whatever" dataProvider="{allMyData}" click="whateverList_click(event)"> </s:List>
<fx:Script>
var whatWasClicked:String = whatever.dataProvider.getItemAt(whatever.selectedIndex).label;
</fx:Script>
Boo ya.

<s:List id="lstDesc" width="100%" height="100%">
<s:change>
Descselected();//do your stuff here
</s:change>
</s:List>
in flash builder.

Related

Laravel Livewire Life hook livewire, v.2.11 updated/updating

When it try trigger to updated life hook when property is changed/updated not work
example
...
public function updatedName($name){
dd($this->name);
}
and I find this message from livewire doc.
Please note that mutating a property directly inside a Livewire component class doesn't trigger any of the updating/updated hooks.
Please. do someone can explain in detail this message from https://laravel-livewire.com/docs/2.x/lifecycle-hooks meaning and what should be done instead
The warning means that the Lifecycle Hooks are not called when you update a property inside the PHP component class.
An example usage is to catch when a user updates a property via the wire:model attribute.
class HelloWorld extends Component
{
public $foo;
public function updatedFoo($value)
{
//
}
public function mount()
{
$this->foo = "New Value";
// updatedFoo will NOT be called
}
}
<input type="text" wire:model="foo" />
<!-- Entering text into this field will cause the hook to be called -->
try this
public $name;
public function updatedName($value)
{
// if you want get value
dd($value);
// if you want change name to new value
$this->name = $value
}

How to get current page from Navigation in ionic 2

I am new to Ionic2, and I am trying to build dynamic tabs based on current menu selection. I am just wondering how can I get current page using navigation controller.
...
export class TabsPage {
constructor(navParams: NavParams,navCtrl:NavController) {
//here I want to get current page
}
}
...
From api documentation I feel getActiveChildNav() or getActive() will give me the current page, but I have no knowledge on ViewController/Nav.
Any help will be appreciated. Thanks in advance.
Full example:
import { NavController } from 'ionic-angular';
export class Page {
constructor(public navCtrl:NavController) {
}
(...)
getActivePage(): string {
return this.navCtrl.getActive().name;
}
}
Method to get current page name:
this.navCtrl.getActive().name
More details here
OMG! This Really Helped mate, Tons of Thanks! #Deivide
I have been stuck for 1 Month, Your answer saved me. :)
Thanks!
if(navCtrl.getActive().component === DashboardPage){
this.showAlert();
}
else
{
this.navCtrl.pop();
}
My team had to build a separate custom shared menu bar, that would be shared and displayed with most pages. From inside of this menu component.ts calling this.navCtrl.getActive().name returns the previous page name. We were able to get the current page name in this case using:
ngAfterViewInit() {
let currentPage = this.app.getActiveNav().getViews()[0].name;
console.log('current page is: ', currentPage);
}
this.navCtrl.getActive().name != TheComponent.name
or
this.navCtrl.getActive().component !== TheComponent
is also possible
navCtrl.getActive() seems to be buggy in certain circumstances, because it returns the wrong ViewController if .setRoot was just used or if .pop was just used, whereas navCtrl.getActive() seems to return the correct ViewController if .push was used.
Use the viewController emitted by the viewDidEnter Observable instead of using navCtrl.getActive() to get the correct active ViewController, like so:
navCtrl.viewDidEnter.subscribe(item=> {
const viewController = item as ViewController;
const n = viewController.name;
console.log('active page: ' + n);
});
I have tested this inside the viewDidEnter subscription, don't know about other lifecycle events ..
Old post. But this is how I get current page name both in dev and prod
this.appCtrl.getActiveNav().getActive().id
Instead of
...
...
//In debug mode alert value is 'HomePage'
//In production/ signed apk alert value is 'n'
alert(activeView.component.name);
if (activeView.component.name === 'HomePage') {
...
...
Use this
...
...
//In debug mode alert value is 'HomePage'
//In production/ signed apk alert value is 'HomePage'
alert(activeView.id);
if (activeView.id === 'HomePage') {
...
...
Source Link
You can use getActive to get active ViewController. The ViewController has component and its the instance of current view. The issue is the comparsion method. I've came up to solution with settings some field like id:string for all my Page components and then compare them. Unfortunately simple checking function name so getActive().component.name will break after minification.

How to avoid duplicate name while creating Sitecore item

I'm facing a problem in my Sitecore project. As we are working in a team, we can't track all the item who has created and what name they have given. The problem is, people are creating the item with same name. This is causing some serious problem while moving the items to different environments.
What I want is, while creating the Sitecore item, pipeline method should execute and validate whether its immediate parent already has the same item name.
For example : Parent A has 3 subitems called Child1, Child2, Child3, when developer tried to create a item with name Child2 the popup/alert should display and not to allow him to create the item.
Please help me with this.
You can add your own handler to item:creating event and check if the parent already contains a child with proposed name.
Here is nice post describing how to prevent duplicates items in Sitecore. I've copied the following code from there:
<event name="item:creating">
<handler type="YourNameSpace.PreventDuplicates, YourAssembly" method="OnItemCreating" />
</event>
namespace YourNamespace
{
public class PreventDuplicates
{
public void OnItemCreating(object sender, EventArgs args)
{
using (new SecurityDisabler())
{
ItemCreatingEventArgs arg = Event.ExtractParameter(args, 0) as ItemCreatingEventArgs;
if ((arg != null) && (Sitecore.Context.Site.Name == "shell"))
{
foreach (Item currentItem in arg.Parent.GetChildren())
{
if ((arg.ItemName.Replace(' ', '-').ToLower() == currentItem.Name.ToLower())
&& (arg.ItemId != currentItem.ID))
{
((SitecoreEventArgs)args).Result.Cancel = true;
Sitecore.Context.ClientPage.ClientResponse.Alert
("Name " + currentItem.Name + " is already in use.Please use another name for the page.");
return;
}
}
}
}
}
}
}
I have a blog post out for this which uses the item create / save event and uses index search to identify duplicates. This was implemented and tested with Sitecore 7.2. Here's the config used:
<sitecore>
<events>
<event name="item:creating">
<handler type="MySite.Customizations.Customized_Sitecore.UniqueItemNameValidator, MySite" method="OnItemCreating" />
</event>
<event name="item:saving">
<handler type="MySite.Customizations.Customized_Sitecore.UniqueItemNameValidator, MySite" method="OnItemSaving" />
</event>
</events>
</sitecore>

Flex List Within a List?

I am trying to display a small set of hierarchical data and have found the AdvancedDataGrid so terrible in how it handles layout I am going to try and approach it another way using Spark Lists.
I am getting from a MySQL database an ArrayCollection of Lessons. Each Lesson has a parent Topic (I have included a TopicName field within each Lesson for ease) and I want to display the Lessons after grouping them by their respective Topics.
I could create a hierarchical data structure, possibly by using a GroupingCollection2, and wondered if I could display a Spark List of Topics and within the topicItemRenderer I create display a Spark List of Lessons for the given Topic?
Any thoughts very welcome.
Chris
To create a grouped list of data I replaced my AdvancedDataGrid with a Spark List within a Spark List. It now has a layout which is predictable and sizes properly. In my case I know that I only have to display approximately 20 items in my grouped List so I don't really have any performance issues.
This is how I did it:
General -
I created a new mxml component dedicated to the list of Lessons. I organise my code following a Model, View, Presenter pattern so I created LessonList_View (mxml) and LessonList_Presenter (ActionScript class). I have a Model class (Singleton) which the presenter classes instantiate to put/get data. The Model raises events when properties change informing the presenters, who have eventListeners, of the change so that they can update their local properties of which the views are bound. The Model calls PHP methods in a Amfphp Service to acquire data from the MySQL database.
Prepare Data -
I have a relational MySQL database containing a table of Lessons and a table of Topics. Each Lesson has to have one parent Topic. A Topic will have many Lessons. I am using Amfphp to get a subset of Lessons data. Each Lesson row from the database is mapped to a Flex class giving me an ArrayCollection of strongly typed value objects of Type VoLesson. To make life simpler I included the topicName field in my VoLesson ActionScript class, only the topicId is available within the MySQL table, and included this in my SELECT statement when getting the data. I also sort the data by Topic and then by Lesson here so its ready for the next step.
Next I need to create an Array Collection containing ArrayCollections of Lessons of the same Topic. This way, I figured, I can have a parent Spark List displaying Topics and within the ItemRenderer for each Topic List Item I can have a List of Lessons.
Once my LessonList_Presenter has got an ArrayCollection of VoLessons I iterate through it. A new, temporary, ArrayCollection of Lessons (_topicLessons) is populated with Lessons until the topicName changes whereupon I add the current _topicLessons ArrayCollection of VoLessons into a parent ArrayCollection (courseTopicLessons).
The function is as follows:
private function updateCourseTopicLessons():void {
// Reset courseTopicLessons.
this.courseTopicLessons = new ArrayCollection();
// Create a variable to hold the last topicName.
var _topicName:String = "";
// Create an ArrayCollection to hold all of the Lessons for a single Topic.
var _topicLessons:ArrayCollection = new ArrayCollection();
// Iterate through the courseLessons.
for each(var _lesson:VoLesson in this.courseLessons)
{
// check to see if this lesson has a different topicName.
if (_lesson.topicName != _topicName) {
//trace("Different Topic: " + _lesson.topicName);
// Add the previous _topicLessons into the courseTopicLessons ArrayCollection.
if (_topicLessons.length > 0) {
//trace("Adding _topicLessons " + _topicLessons.length + " to courseTopicLessons");
this.courseTopicLessons.addItemAt(_topicLessons, 0)
}
// This is a new Topic. Reset _topicLessons.
//trace("Reset _topicLessons");
_topicLessons = new ArrayCollection();
// Update _topicName.
_topicName = _lesson.topicName;
}
// Add the Lesson to _topicLessons.
//trace("Add Lesson: " + _lesson.lessonTitle + " to _topicLessons")
_topicLessons.addItemAt(_lesson, 0);
}
// Add the previous _topicLessons into the courseTopicLessons ArrayCollection.
if (_topicLessons.length > 0) {
//trace("Adding final _topicLessons " + _topicLessons.length + " to courseTopicLessons")
this.courseTopicLessons.addItemAt(_topicLessons, 0)
}
//trace(this.courseTopicLessons)
}
I used .addItemAt() to keep the sort order correct.
Views and ItemRenderers -
In my LessonList_View I created the List and set it as follows:
<!-- Lessons List -->
<s:List
id="lessonList"
dataProvider="{presenter.courseTopicLessons}"
itemRenderer="views.LessonListTopicItemRenderer_View"
borderVisible="false"
borderColor="0xff69b4"
preventSelection="true"
contentBackgroundAlpha="0">
<s:layout>
<s:VerticalLayout
useVirtualLayout="false"
requestedMinRowCount="1"
gap="8"
paddingTop="8" paddingBottom="8"/>
</s:layout>
</s:List>
I used the borders when checking everything to see the extents of the Lists.
My data provider is an ArrayCollection of ArrayCollections. I want to display List of Topics and within each Topic List Item I want to display a List of Lessons. To display the Topics I know that each ArrayCollection within the parent ArrayCollection will have at least 1 VoLesson (I hope you're following this!). I can display the topicName value from this item. Here is my code for the Lesson List's ItemRenderer:
<s:ItemRenderer
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:presenters="presenters.*"
width="100%" height="100%"
autoDrawBackground="false">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<presenters:LessonListTopicItemRenderer_Presenter id="presenter"/>
</fx:Declarations>
<fx:Script>
<![CDATA[
import models.Globals;
import vo.VoLesson;
override public function set data( value:Object ) : void {
super.data = value;
// Check to see if the data property is null.
if (value== null)
return;
// If the data property is not null.
var _lesson:VoLesson = VoLesson(value[0]);
topicLabel.text = _lesson.topicName;
}
]]>
</fx:Script>
<s:VGroup gap="8" width="100%">
<!-- Divider line between Topics -->
<s:Line id="topicDividerLine" width="100%">
<s:stroke>
<s:SolidColorStroke color="{presenter.selectedActivityColour_Mid}" weight="1" />
</s:stroke>
</s:Line>
<!-- Topic Label -->
<s:Label
id="topicLabel"
styleName="topicStyle"
color="{presenter.selectedActivityColour}"
maxWidth="{presenter.lessonsListTopicColumnWidth}" />
<s:HGroup paddingLeft="{Globals.LESSONS_LIST_TOPIC_COLUMN_WIDTH}">
<s:List
id="lessonList"
dataProvider="{data}"
borderColor="0xadff2f"
itemRenderer="views.LessonListLessonItemRenderer_View"
borderVisible="false"
preventSelection="true">
<s:layout>
<s:VerticalLayout
useVirtualLayout="false"
requestedMinRowCount="1"
gap="16"
paddingTop="8" paddingBottom="8"/>
</s:layout>
</s:List>
</s:HGroup>
</s:VGroup>
The key thing to remember is that the ItemRenderer will be passed only the data for an individual item in the List, in this case an ArrayCollection of VoLesson objects. Within the element I get the topicName for the first item in the ArrayCollection of VoLessons passed in as 'data' and set my Label's text property.
Below the Topic Label I have my List of Lessons which has the same data provider, an ArrayCollection of VoLesson objects for the same Topic. The ItemRenderer for this List is as follows:
<s:ItemRenderer
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:views="views.*"
xmlns:presenters="presenters.*"
height="100%"
autoDrawBackground="false">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<presenters:LessonListLessonItemRenderer_Presenter id="presenter"/>
</fx:Declarations>
<fx:Script>
<![CDATA[
import vo.VoLesson;
override public function set data( value:Object ) : void {
super.data = value;
// Check to see if the data property is null.
if (value== null)
return;
// If the data property is not null.
var _lesson:VoLesson = VoLesson(value);
lessonLabel.text = _lesson.lessonTitle;
}
]]>
</fx:Script>
<s:HGroup gap="8" verticalAlign="middle">
<views:IconLesson_View />
<s:Label
id="lessonLabel"
styleName="lessonStyle"
color="{presenter.textDarkGrey}"/>
</s:HGroup>
Remember that the 'data' object for this ItemRenderer, and there will be one for each item in the List of Lessons, will be a single VoLesson object. In the element I get the lessonTitle property from the VoLesson and set the lessonLabel Label's text property.
Final List
The List appears as follows:
I have spent many days trying to coerce an AdvancedDataGrid to size itself and layout the content properly, it was dreadful. Yesterday I decided to start again and this works so much better. For a simple grouped list I would recommend a similar approach.
Regards
Chris
You could do it that way and it would work, But its not a good idea if you have a lot data. You would have to worry about item renderers. I would probably use a tree and create custom item renderers if need be. May be some code might help.

grails populating g:select from query

Trying to become a grails convert I have begun converting an existing application to Grails and Groovy. It works very well but I get stuck on the conversion of select tags.
I have a domain class:
package todo
class Person {
String ssn
String firstname
String familyname
String role
String emailname
String emailserver
...
When creating a new "todo" task an owner may be assigned from those persons in the system who are developers and I get this working (a fairly direct translation from PHP):
<select id="owner" name="owner">
<option>Noboby ...</option>
<g:each in="${Person.list()}">
<g:if test="${it?.role=='developer'}">
<option value="${it?.id}">${it?.firstname} ${it?.familyname}</option>
</g:if>
</g:each>
</select>
But every attempt to make it more "Grails-ish" fails. How can it be moulded into Grails v2.2.1 code? I spent hours reading, trying, failing.
If you woulkd like to make it more Grails style, you should perform all your logic within controllers \ services not in the view.
Assuming you have a view createTodo in the folder person and the PersonController, then modify your createTodo action like this:
class PersonController {
def createTodo() {
def developers = Person.findAllWhere(role: 'developer')
[developers: developers, ... /* your other values */]
}
}
So you don't need to handle with database operations in your view.
Next step is to use the g:select tag like this:
<g:select name="owner" from="${developers}" optionValue="${{'${it.firstName} ${it.familyName}'}}" noSelection="['null':'Nobody ...']" optionKey="id" value="${personInstance?.id}" />
Try this code:
<g:select optionKey="id" from="${Person.findAllByRole('developer')}" optionValue="${{it.fullName}}" value="${yourDomainInstance?.person?.id}" noSelection="['null':'Nobody']"></g:select>
And in your class:
class Person {
....
String getFullName(){
it?.firstname+' '+ it?.familyname
}
static transients = ['fullName']
....
}
See g:select tag for more details
Finally, I got it working as I want to and it works (almost) according to the #"Mr. Cat" solution. One little detail, though, 'it' does not exist in the class so the getFullName method had to become:
String getFullName(){
this?.firstname+' '+ this?.familyname
}
Up and working, thank you for all help.