cellBrowser placed in composite - do I have to attach directly to the rootpanel (or rootlayoutpanel) - gwt2

when using a cellbrowser and adding that widget to a flowpanel (to be placed wherever, downstream), for some reason the end result is dead (a blank screen)...vs if I add directly to the rootpanel (or layout panel)

Also had the same problem. I had to use a <g:HTMLPanel> as the parent of the CellBrowser (as seen in the GWT Showcase).

Do you have some sample code that will reproduce this?

below is the code for the composite...essentially, what I'd like to do is in another class, attached this composite to a flowpanel and do whatever with it...but, the reality is, I have to attach is directly to the RootPanel (or RootLayoutPanel)...any other abstraction causes it to bail
for example
FlowPanel fp = new FlowPanel();
V2_M76Rolodex v = new V2_M76Rolodex();
fp.add(v); // not going to work
RootPanel.get.add(v) works
public class V2_M76Rolodex extends Composite {
/*
a bunch of code here for getting data and
populating the tree - works, not at issue or relevant
*/
public V2_M76Rolodex() {
TreeViewModel model = new CustomTreeModel();
CellBrowser browser = new CellBrowser(model, null);
browser.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
browser.addStyleName("rolodex_cell_browser");
initWidget(browser);
}
}

Related

notifyDatasetchanged not working for ArrayAdapter

I am trying to implement 2 AutoCompleteTextView. First one holds the value, on click of one of them will populate the data in second AutoCompleteTextView, all works and data gets loaded correctly however when I try to call notifyDataSetChanged on the second adapter which populates the second field that does not get changed.
I also wrote that piece of code inside a Handler too, however that does not seems to work either.
branchAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,branchNames);
et7.setAdapter(branchAdapter);//et7 is the AutoCompleteTextView //branchname is the ArrayList
in some method I clean up the ArrayList and add the new data into it and then call notifyDataSetChanged like below
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
branchAdapter.notifyDataSetChanged();
}
});
Which is not updating the list. What should be the correct way here to update data?
#Saty, I guess i am a little late to the party. I am answering, keeping in mind that, it may help somebody in future.
Cleanup the adapter as well using branchAdapter.clear() method. Then add new items to the adapter using branchAdapter.addAll(String... items) method. Now, call branchAdapter.notifyDataSetChanged() method. This will work.
Try resetting listview instead.
ListView lv = (ListView)findViewById(R.id.lv);
ArrayAdapter adapter = new ArrayAdapter(/*with all parameters*/);
lv.setAdapter(adapter);

Invoking Method of Presenter on Activation

I'm using Smart Client Software Factory 2008. In the module controller, I have code that creates a new child controller only if it hasn't been created, by doing something like the following:
Dim key = "Item-" + item.ID.ToString()
Dim childWorkItem = Me.WorkItem.WorkItems.Get(Of ControlledWorkItem(Of ItemWorkItemController))(key)
If childWorkItem Is Nothing Then
childWorkItem = Me.WorkItem.WorkItems.AddNew(Of ControlledWorkItem(Of ItemWorkItemController))(key)
Else
childWorkItem.Activate()
End If
Multiple items reuse the same key, so when that action is triggered, it shows the tab instead of creating a new instance of it. This works great.
However, there is one drawback. Once activated, I need to run a check within that item's presenter. So I need to call a method on the presenter. Is there a way to invoka a method on the presenter, or is there an event that runs on the view when the work item is activated? I'm not sure how to make that happen?
Thanks.
If you are using a Smart Part as your View you should be able to accomplish this using the IWorkspace.SmartPartActivated event.
This is how I have it setup in my project. I apologize, my code is all in C# but you should be able to apply it in VB relatively easily.
The WorkItemController class has the Activate method setup like this
ISmartPartView _smartPartView
public void Activate()
{
IWorkspace contentWorkspace = this.WorkItem.Workspaces[WorkspaceNames.ShellContentWorkspace];
contentWorkspace.Activate(_smartPartView);
WorkItem.Activate();
}
In the ISmartPartView Presenter class you should be able to create a handler for the SmartPartActivated event like this:
IWorkspace contentWorkspace = this.WorkItem.Workspaces[WorkspaceNames.ShellContentWorkspace];
contentWorkspace.SmartPartActivated += workSpaceSmartPart_ActivatedHandler;
In the workSpaceSmartPart_ActivatedHandler event handler, you can check the SmartPart being activated and if its your ISmartPartView class you can run the desired code.

How to create new instance of a view/viewmodel when navigation occurs with Prism

I am trying to control when a new view is created and when an existing view is shown.
This is a very similar scenario as outlined in the "Navigating to Existing Views" section in the Prism documentation, but I can't get it to work fully:
http://msdn.microsoft.com/en-us/library/gg430861(v=pandp.40).aspx
I am finding I can create the view/view model to begin with ok, but I am then unable to create a new instance of it. I.e. I want more than one instance to exist at once.
Here's an example of the view model:
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class DataEntryPageViewModel : INavigationAware, IRegionMemberLifetime
{
private Guid id;
[ImportingConstructor]
public DataEntryPageViewModel()
{
id = Guid.NewGuid();
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
// In actual fact there would be more logic here to determine
// whether this should be shown to the user
return false;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
}
public bool KeepAlive
{
// For the purposes of this example we don't want the view or the viewModel
// to be disposed of.
get { return true; }
}
}
I am navigating to this as follows:
m_RegionManager.RequestNavigate(
"MainRegion",
new Uri("/DataEntryPageView", UriKind.Relative));
So the first time I call the above the view is shown.
The next time I call RequestNavigate the IsNavigationTarget is hit and it returns false. What I then want it to do is to create a new instance but that doesn't happen. I know it's not happening because the constructor does not get hit and the UI does not update to show the new instance of the view.
Any ideas how I can make it create a new instance?
Many thanks,
Paul
Edit
I have noticed that the second time I call RequestNavigate (to request another instance of the same view) the callback reports an error "View already exists in region." It therefore seems that I can have multiple instances of different views in a region, but not multiple instances of the same view. My understand of this isn't great though so I could be wrong.
Why are you not creating the view when you want a new one to be created? It looks to me like you are using MEF.
Use the container to resolve a new instance of your view
Add the new instance of the view to the MainRegion
Then call Navigate and handle the appropriate logic in IsNavigationTarget
You should use the [Export] attribute in your view with a contract name: [Export("DataEntryPageView")].
I have now been able to get this to work, it was because I didn't have
[PartCreationPolicy(CreationPolicy.NonShared)]
on the class declaration of the view. I had it on the ViewModel.
So this is now resulting in the behaviour I expected.
Thanks though to Zabavsky and Alan for your suggestions.

I can't load my SmartGWT Datasource

I'm modifying an example of the built-in-ds. The way this example works is that you need to select a datasource, and then a table gets filled with data from there. The idea is to show how the same component can adapt to multiple data sources. I've managed to run the example and it works, but I'm trying to modify it so you skip the first step - there's only one data source that gets loaded "into" the table. What puzzles me is that this should be trivial but for some reason it's not. I'll paste just the different parts of code, this one works:
// we create a list of datasources
ListGrid grid = new ListGrid();
grid.setLeft(20);
grid.setTop(75);
grid.setWidth(130);
grid.setLeaveScrollbarGap(false);
grid.setShowSortArrow(SortArrow.NONE);
grid.setCanSort(false);
grid.setFields(new ListGridField("dsTitle", "Select a DataSource"));
// I'm just loading the one I need
grid.setData(new ListGridRecord[] { new DSRecord("predmeti", "predmeti")});
grid.setSelectionType(SelectionStyle.SINGLE);
grid.addRecordClickHandler(new RecordClickHandler() {
public void onRecordClick(RecordClickEvent event) {
DSRecord record = (DSRecord) event.getRecord();
bindComponents(record.getDsName());
}
});
grid.draw();
and this is the bindComponents method:
private void bindComponents(String dsName) {
DataSource ds = DataSource.get(dsName);
boundList.setDataSource(ds);
boundViewer.setDataSource(ds);
boundForm.setDataSource(ds);
boundList.fetchData();
newBtn.enable();
saveBtn.disable();
}
and this works as it should. Now, since I only have one data source, I can skip the grid and just make the call to bindComponents:
bindComponents();
And bindComponents looks like this:
private void bindComponents() {
DataSource ds = DataSource.get("predmeti");
boundList.setDataSource(ds);
boundViewer.setDataSource(ds);
boundForm.setDataSource(ds);
boundList.fetchData();
newBtn.enable();
saveBtn.disable();
}
I can't see why the second doesn't work, it breaks on boundList.setDataSource(ds);. I inspected it in Debug mode, an object is returned and it looks "the same" in both cases but for some reason it doesn't work in the second example, so I'm guessing I'm instancing the data source too early or, somehow, just plain wrong :)
Everything was fine with the datasources, the problem is trivial and I must have just been tired - the boundList object at the time of this call boundList.setDataSource(ds); was not yet instantiated. I kept getting Null pointer exception, but I thought there was something wrong with the DataSource.

Encapsulating common logic (domain driven design, best practices)

Updated: 09/02/2009 - Revised question, provided better examples, added bounty.
Hi,
I'm building a PHP application using the data mapper pattern between the database and the entities (domain objects). My question is:
What is the best way to encapsulate a commonly performed task?
For example, one common task is retrieving one or more site entities from the site mapper, and their associated (home) page entities from the page mapper. At present, I would do that like this:
$siteMapper = new Site_Mapper();
$site = $siteMapper->findByid(1);
$pageMapper = new Page_Mapper();
$site->addPage($pageMapper->findHome($site->getId()));
Now that's a fairly trivial example, but it gets more complicated in reality, as each site also has an associated locale, and the page actually has multiple revisions (although for the purposes of this task I'd only be interested in the most recent one).
I'm going to need to do this (get the site and associated home page, locale etc.) in multiple places within my application, and I cant think of the best way/place to encapsulate this task, so that I don't have to repeat it all over the place. Ideally I'd like to end up with something like this:
$someObject = new SomeClass();
$site = $someObject->someMethod(1); // or
$sites = $someObject->someOtherMethod();
Where the resulting site entities already have their associated entities created and ready for use.
The same problem occurs when saving these objects back. Say I have a site entity and associated home page entity, and they've both been modified, I have to do something like this:
$siteMapper->save($site);
$pageMapper->save($site->getHomePage());
Again, trivial, but this example is simplified. Duplication of code still applies.
In my mind it makes sense to have some sort of central object that could take care of:
Retrieving a site (or sites) and all nessessary associated entities
Creating new site entities with new associated entities
Taking a site (or sites) and saving it and all associated entities (if they've changed)
So back to my question, what should this object be?
The existing mapper object?
Something based on the repository pattern?*
Something based on the unit of work patten?*
Something else?
* I don't fully understand either of these, as you can probably guess.
Is there a standard way to approach this problem, and could someone provide a short description of how they'd implement it? I'm not looking for anyone to provide a fully working implementation, just the theory.
Thanks,
Jack
Using the repository/service pattern, your Repository classes would provide a simple CRUD interface for each of your entities, then the Service classes would be an additional layer that performs additional logic like attaching entity dependencies. The rest of your app then only utilizes the Services. Your example might look like this:
$site = $siteService->getSiteById(1); // or
$sites = $siteService->getAllSites();
Then inside the SiteService class you would have something like this:
function getSiteById($id) {
$site = $siteRepository->getSiteById($id);
foreach ($pageRepository->getPagesBySiteId($site->id) as $page)
{
$site->pages[] = $page;
}
return $site;
}
I don't know PHP that well so please excuse if there is something wrong syntactically.
[Edit: this entry attempts to address the fact that it is oftentimes easier to write custom code to directly deal with a situation than it is to try to fit the problem into a pattern.]
Patterns are nice in concept, but they don't always "map". After years of high end PHP development, we have settled on a very direct way of handling such matters. Consider this:
File: Site.php
class Site
{
public static function Select($ID)
{
//Ensure current user has access to ID
//Lookup and return data
}
public static function Insert($aData)
{
//Validate $aData
//In the event of errors, raise a ValidationError($ErrorList)
//Do whatever it is you are doing
//Return new ID
}
public static function Update($ID, $aData)
{
//Validate $aData
//In the event of errors, raise a ValidationError($ErrorList)
//Update necessary fields
}
Then, in order to call it (from anywhere), just run:
$aData = Site::Select(123);
Site::Update(123, array('FirstName' => 'New First Name'));
$ID = Site::Insert(array(...))
One thing to keep in mind about OO programming and PHP... PHP does not keep "state" between requests, so creating an object instance just to have it immediately destroyed does not often make sense.
I'd probably start by extracting the common task to a helper method somewhere, then waiting to see what the design calls for. It feels like it's too early to tell.
What would you name this method ? The name usually hints at where the method belongs.
class Page {
public $id, $title, $url;
public function __construct($id=false) {
$this->id = $id;
}
public function save() {
// ...
}
}
class Site {
public $id = '';
public $pages = array();
function __construct($id) {
$this->id = $id;
foreach ($this->getPages() as $page_id) {
$this->pages[] = new Page($page_id);
}
}
private function getPages() {
// ...
}
public function addPage($url) {
$page = ($this->pages[] = new Page());
$page->url = $url;
return $page;
}
public function save() {
foreach ($this->pages as $page) {
$page->save();
}
// ..
}
}
$site = new Site($id);
$page = $site->addPage('/');
$page->title = 'Home';
$site->save();
Make your Site object an Aggregate Root to encapsulate the complex association and ensure consistency.
Then create a SiteRepository that has the responsibility of retrieving the Site aggregate and populating its children (including all Pages).
You will not need a separate PageRepository (assuming that you don't make Page a separate Aggregate Root), and your SiteRepository should have the responsibility of retrieving the Page objects as well (in your case by using your existing Mappers).
So:
$siteRepository = new SiteRepository($myDbConfig);
$site = $siteRepository->findById(1); // will have Page children attached
And then the findById method would be responsible for also finding all Page children of the Site. This will have a similar structure to the answer CodeMonkey1 gave, however I believe you will benefit more by using the Aggregate and Repository patterns, rather than creating a specific Service for this task. Any other retrieval/querying/updating of the Site aggregate, including any of its child objects, would be done through the same SiteRepository.
Edit: Here's a short DDD Guide to help you with the terminology, although I'd really recommend reading Evans if you want the whole picture.