How to notifying container class in mvvm pattern - mvvm

In my silver light application i have two classes: Container and Field.
Container contains a list of Fields. Now,
whenever an Field(in the list) receives
a message I want to notify Container object to
perform some logic.
Field object should not contain any reference of Container. i need to achieve this using INotifyPropertyChanged.
Please suggest a simple solution using INotifyPropertyChanged.

Your Container object could subscribe to the PropertyChanged event of each of it's child Field objects.
If it's not a property change your interested in directly you could implement your own custom event for the Field object.
It's hard to given an example without knowing your exact situation... but here goes.
E.g Pseudo-code: (on the Container object)
public void AddField(Field field)
{
// attach to the new fields property changed event
field.PropertyChanged += OnFieldPropertyChanged;
// add the new field to this container's collection
this.Fields.Add(field);
}
private void OnFieldPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// do something
}
You may also want to check out ObservableCollections.

Related

Sync data from component back to the calling page in ionic 5

In my Ionic 5 project, I have created a custom component and passing the data from a Page.
HomePage HTML:
<app-userItem [inUser]="user (outSync)="syncUser($event)"></app-userItem>
Where user is.
let user = {
Name: 'Test User',
Age: 23
}
Now I want if inside component UserItem I change the value of Age, it should be synced back in the Homepage user variable. It is not happening automatically.
To Achieve this I am using the outSync event emit method for now. My question is as I am using [] to pass value of parameter inUser, shouldn't the user variable be in sync from both sides?
Now I want if inside component UserItem I change the value of Age, it should be synced back in the Homepage user variable. It is not happening automatically.
I think the reason why it's not happening automatically is because Angular compares the object identity to see if something has changed, but in your case, user === user is true even after changing user.age because the instance is still the same.
It doesn't mean the object is not being updated – it's just that Angular doesn't know that because the instance of the object is the same so as far as Angular knows, nothing have been changed.
A better approach would be if the UserItemComponent only presents the data, but doesn't change it directly (which would make it a dumb or presentational component).
For example, if that component could change both the name and the age properties, it'd be better if it just notifies the parent that those properties should be changed, and it's the parent who updates the user.
<app-userItem
[inUser]="user
(updateAge)="updateAge($event)"
(updateName)="updateName($event)"
></app-userItem>
And then the parent component would modify the data, creating a new instance of the object so that the child receives the update:
public updateAge(newAge: number): void {
this.user = {
...this.user,
age: newAge
};
}

RecyclerView on Multiple Activity

I have an app that depends heavily on recyclerview.. Each activity has different model and layout for them.. So do I need to write separate adapters for all of them.?? Or could I have a base adapter which can have on create view holder, onbind view holder which would reduce the amount of repetitive code..PS. I also need onclick listener so, I wanted to include that in the base adapter..
What is the best way?? And if I can write a base adapter please give me some code samples..
Thanks in Advance...
Each activity has different model and layout for them.. So do I need
to write separate adapters for all of them
Adapters are responsible for providing views that represent items in a data set, used by the RecyclerView. Now if those items in your ReyclerView are same across all the Activities then you can just have a single RecyclerView.Adapter
I also need onclick listener so, I wanted to include that in the base
adapter.. What is the best way??
You can check this SO post for detailed implementation, but I am summarizing it briefly.
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position) {
// do whatever
}
})
);
And provide RecyclerItemClickListener class, that implements RecyclerView.OnItemTouchListener interface
And if I can write a base adapter please give me some code samples.
You need to clarify what exactly needs to be implemented in BaseAdapter for anyone to help you
yes it is possible
enter code here holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (modelArrayList.get(position).heading.equals("maps")){
Intent intent = new Intent(holder.button.getContext(),MainActivity2.class);
holder.button.getContext().startActivity(intent);
}
if (modelArrayList.get(position).heading.equals("calls")){
Intent intent = new Intent(holder.button.getContext(),MainActivity3.class);
holder.button.getContext().startActivity(intent);
}

GXT 3 dynamically update an element in a treeStore

i'm currently using GXT 3 to display elements in a Tree.
These elements are retrieved from database and identified in the Tree by their id (by that, I mean that the id is the ModelKeyProvider of my store).
I also made it possible for users to create objects locally in the tree with the following code:
private Tree<EntityDAO, String> tree;
private TreeStore<EntityDAO> store;
int count = 1;
// instanciation and irrelevant stuff
...
EntityDAO sel = tree.getSelectionModel().getSelectedItem();
EntityDAO child = new EntityDAO();
child.setId((long) count);
store.add(store.getParent(sel), child);
count++;
tree.setExpanded(sel, true);
tree.getSelectionModel().select(child, false);
As you can see, i set a temporary id (count) to my local object.
The issue occurs when I save my object in database. A permanent id is then set to my EntityDAO but when i try to set this id to my local object to sync it with the database, it doesn't work.
I've tried to modify the child id directly
child.setId(result);
tree.update(child);
I've tried to add a copy of my object with the proper id, and then to remove my object from the tree
EntityDAO newPR = child;
newPR.setId(result);
store.add(store.getParent(child), newPR);
store.remove(child);
But the display is never updated. Any clue?
Let's discuss about the first way you tried, the update method:
child.setId(result);
tree.update(child);
From the update method API state this :
Replaces the item that matches the key of the given item, and fires a
StoreUpdateEvent to indicate that this change has occurred. Any
changes to the previous model via it's record instance will be lost
and the record will be removed. This will not cause the sort or filter
to be re-applied to the object. Overrides: update(...) in Store
Parameters: item the new item to take its place in the Store.
So basically, the update method will replace the item inside the store that have the same key with your parameter. Your data have a new key that doesn't exist inside the store, that's why it doesn't effected anything to your tree display.
Second, let's discuss the create a copy of your object and set it with the proper id:
EntityDAO newPR = child;
newPR.setId(result);
store.add(store.getParent(child), newPR);
store.remove(child);
This way actually will work, but you only have one small problem. The first line of your code actually just give you a variable that have a reference to your old object (the child object), so whenever you remove the child, the newPR also removed. You should really create a new object using the constructor, here how I think you should do it:
EntityDAO newPR = new EntityDAO();
newPR.setId(result);
newPR.setOtherProperty(child.getOtherProperty());
// just copy all property of child to newPR
store.add(store.getParent(child), newPR);
store.remove(child);
Hope this can help you.

Use a GWT Entity Proxy to temporarly save changes. Implementing 'Apply changes' pattern

I have a CellTable<UserProxy>. So in other words it manages directly entity proxies of my database entities. With that I use an AsyncDataProvider<UserProxy> that fetches the data using a request factory.
The cells of my columns are EditTextCell. And I added a FieldUpdater<UserProxy, String> to edit the values. Except here is my problem: if I update the value of the entity and save it immediately it works fine, but I don't know how I can differ the save to a click on a button later.
Basically, I want to implement the Apply-changes pattern (see: http://patterns.holehan.org/Review/ApplyChanges), so I want the user to be able to edit several values in the table and once he is done he can click the 'apply' button which will save all the changes.
So my idea for this was to change the value in the proxy entity without invoking save and then saving all modified entities in the clickhandler of the button.
But to make the change to a value in a proxy entity, I must call ctx.edit(user) first:
nameColumn.setFieldUpdater(new FieldUpdater<UserProxy, String>() {
#Override
public void update(int index, UserProxy object, String value) {
if (!value.equals(object.getName())) {
UserRequest ur = presenter.getClientFactory().getRequestFactory().getUserRequest();
ur.edit(object);
object.setName(value);
saveButton.setEnabled(true);
}
}
});
And this makes it impossible to save them afterwards in the clickhandler of the apply button:
private void saveModifications() {
List<UserProxy> items = cellTable.getVisibleItems();
for (UserProxy item : items) {
UserRequest ur = presenter.getClientFactory().getRequestFactory().getUserRequest();
ur.save(item).fire();
}
cellTable.setVisibleRangeAndClearData(cellTable.getVisibleRange(), true);
}
Because calling save(item) throws this exception: java.lang.IllegalArgumentException: Attempting to edit an EntityProxy previously edited by another RequestContext
How to avoid this without having to make yet another class representing the same entity?
You must use a single RequestContext instance where you edit() all your proxies. You can edit() several times the same proxy with no error and no overhead.
So:
store presenter.getClientFactory().getRequestFactory().getUserrequest() in a variable/field somewhere
in the FieldUpdaters, ctx.edit(object).setName(value) will enqueue the changes in the RequestContext; possibly put the UserProxy in a Set too for later reference
in saveModifications, loop over your proxies (possibly only those from the Set built on step 2) and ctx.save(item) and then at the end of the loop ctx.fire()

GWT - Remember state of checkboxes after RangeChangeEvent sent to table

I have CellTable with MultipleSelectionModel attached to it. After some modification of data the table has to be refreshed and new data has to be reloaded from server.
However I need to update checkboxes state for newly loaded data. So I am able to query selection boxes with selectionModel.getSelectedSet() - but now I need to find these objects in table and "check" them.
Because content of objects changes and since they are used as keys in Maps internally in GWT components- I was forced to write "wrapper" over these objects which uses only ID in equals/hashCode.
So basically I save selectedSet before firing event, then iterate over it and invoke setSelected method:
Set<T> selectedSet = selectionModel.getSelectedSet();
RangeChangeEvent.fire(table,...)
if (selectedSet != null)
for (T obj : selectedSet) {
selectionModel.setSelected(obj,true);
}
}
Is there any better approach?
This is what the ProvidesKey is for: create a ProvidesKey instance that returns the ID of your objects to be used as their keys, and pass that instance to your selection model when you build it:
MultiSelectionModel<X> selectionModel = new MultiSelectionModel<X>(new ProvidesKey<X>() {
#Override
public Object getKey(X item) {
return item.getId();
}
});
That way, you shouldn't have anything special to do with your selection model after retrieving updated data: push it to your table and it'll ask the selection model for each object whether it's selected or not, and the selection model will be able to answer based solely on the object's ID, therefore reusing the same selected set as before.