Put an event on the model, or on the controller? - model-view-controller

This is for a client-side MVP program, using Passive View.
I want to allow the user to create a contact and add it to a quote. I want the quote to be notified when the contact is created.
Is it better to do a) or b)?
a) Listen to the model
Pass the contact to the contacts controller, and listen for a saved event on the model
var contact = new Contact()
contact.on('saved', function(contact){ do some stuff })
contactsController.create(contact)
contactsController then loads the contact into the view, user enters some info, hits save, contact is saved to the server, contact.saved event is fired
b) Listen to the controller
contactsController.on('saved', function(contact) { do some stuff })
contactsController.create()
contactsContoller then creates contact model, loads the contact into the view, user enters some info, hits save, contact is saved to the server, contactsController.saved event is fired
Thanks!

I think it depends on the subtle but important difference between wanting to know when a contact gets saved to the database versus wanting to know when a user submits the save contact page. I.e., the controller may not be the only place that saves a contact. If you want to know the former, use the model. If you want to know the latter, use the controller.

I would recommend the following.
User clicks Add a Contact
The View tells the Presenter that a Contact as been added
The Presents execute as Command that handles adding a contact
The Command does the following
Displays a Dialog or View that allows the user to add the contacts.
The Command waits until the user clicks add or OK to confirm the new contact
The Command then updates the Model
The Command tells the right Presenter* that a contact has been added.
Then in the Presenter that handles the Queries, the Update Contact call will find all the relevant Queries and update the contact info. This update may be done through a listener pattern where all the query views register themselves with the presenter.
*The right presenter is whatever presenter you setup to handle the view that displays the queries. Some system could have a unique presenter for displaying queries, in other it may be just be a part of a presenter where the query display is just a section of a larger display.

Related

HowTo: stay on account view while opening a contact on a column

I am using a simple tree view on the left side for a company to see linked entities like opportunities, contacts, etc.,
When I click on a contact, my browser gets redirected to the contact, but I want to stay on the company view and load the contact details into the second or third column or just any sector on that company view.
Getting redirected to each record every time I click a link is annoying because I lose my track and sometimes I want to see the parent details while I see the details of a child record. In this case I want to keep the company view while I can load one contact on the same view without any page load or redirection.
Note: I am using a demo access to Dynamics CRM 2015 online and installed a plugin from a third party to get a tree view. The above is not dependent on my tree view. This can also be done for activities for example which is listed on right column by default. By clicking on an activity, I would like to see the activity details loaded in some panel on the middle column or anywhere I want, without being redirected.
You probably can make do with a Quick View.
Let's say you want to do this trick with Accounts and Contacts, to display info for contacts inside an Account. It goes like this:
Create a lookup inside Account, to Contact entity. Put it on the form (you can make it not visible, doesn't matter).
Create a "Quick View" form inside Contact. They are built similar to normal forms. Include all the info you want to display.
Go back to Account form, INSERT -> Quick View. Select the lookup you made in point 1, and the quick view you just created.
The quick view will display on the Account form, grabbing info from the Contact selected inside the lookup. If you left the new lookup visible, you can play with it and see how it works.
4b. You probably will now need to "link" the treeview with the lookup somehow (since it's third-party I'm unable to offer any insight about it). It will require a bit of javascript for sure.
For more details, as usual, refer to MSDN
Ps: If you want to try it out fast, skip #1 and pick "Primary contact" as field in #3 (it's standad, and most likely already on the form)

Changing form types on custom entity

I have a custom entity with 4 different forms. The entity has a N:1 relationship with the contact entity. The contact lookup is viewable in each of the 4 forms.
I can go to a contact and add a new record for my custom entity. When the form launches, the contact is selected in the lookup field. If I switch to a different form, it loses the contact value in the lookup.
How can I prevent this from happening? After the second form loads and the contact is lost from the lookup, I can press F5 to refresh the page and the contact will then be displayed in the lookup. I could use a javascript to replicate this, but the best user experience is for that page to not have to be reloaded again. It should just load the form and the contact should automatically be selected.
Am I missing something? I find this very perplexing.
You can force a save before changing the form, and on the onLoad of the new form, if you still don't get the value, you can force the values in the form to refresh
Xrm.Page.data.refresh(false);

AngularJS - removing the line between SPA and AJAX data binding

In Angular, speed is the name of the game and rendering views with useful data as quickly as possible is always sought after. Angular allows us to reference data between the Controller and the View seamlessly using Angular's templating engine, which can make rendering views with correctly bound data lightning fast.
For example, lets say we have a simple Angular App which is simply a table of contacts with fields like First Name, Last Name, Phone, Email, and Address. We then want a Details view that appears when you click on a table row. We can wire up the <tr> to change views on click like this
<tr ng-repeat="contact in Contacts" ng-click="showDetails(contact)">
Then we can change the view and "instantly" show contact data in the new view. For example, we can change an <h1> at the top of the page to be Contact - John Smith using the data that was provided in showDetails.
While this data is being shown, more data can be retrieved from the server asynchronously that will then fill in the rest of the fields.
However, what do we do if we want to get to this details page directly from the url? If the contact table was sitting at /contacts and the details page was something like /contacts/detail/1 then attempting to go directly to /contacts/detail/1 would result in the <h1> above to be blank.
This is clearly because we did not use the showDetails() method to invoke the view and pass the clicked contact into it directly. In this case, we would need to take the contact id in the URL and run an AJAX request to get ALL of the data.
My question is, at what point do we draw the line between trying to make our views and data quickly accessible and making them robust?
Robust is a must.
So we need to start there. Then we can move forward to optimize and make data "quickly accessible", as you put it, as much as possible.
In order to do that, every view in an SPA that is directly correlated to a URL needs to be initially stateless. That basically means that a reload on any url will load the desired view correctly and completely.
We can get the best of both worlds by using nested routes. If every route loads only what it needs, but also draws on parent routes (loading them if necessary, or just using them if they have already been provided) then you can achieve both robustness and "quick accessibility" to data.
In your particular example, the base route would be contacts. Then there could be a nested route inside of that which would display the details of a particular contact, contacts/detail/{id}. Loading the base url would load the list of contacts, and loading the details view would load both the list of contacts and the details of a particular contact. To provide quickly accessible data when going to the nested view, we could include logic that checks to see if the parent view data is already loaded, and only load if necessary. Then when navigating from the contacts to the contacts/detail/{id} view, we could quickly display data from the parent view in the child view, while loading data specific to the child view. A reload at contacts/detail/{id} would simply load both. When navigating back to the parent, the parent data would already be loaded.
If you were to use something like ui-router to create complex routes, then you would not use showDetails() to alter the model, you would use showDetails() to alter the route. Then your model would set itself up based on the route, and your view would follow.
For example, you could have something like:
$scope.showDetails = function(contact) {
$state.go('contacts.detail', { contactId: contact.id });
};
Then the controller could use $stateParams to retrieve any data you wanted for the specific contact from the server (asynchronously using promises). You could also include your own flavour of caching/loading via services to manage things like performance if you found it necessary.

how to use razor as user control

Example Scenario:
Let's say I need to create a user control which displays a list of products for specified category (CategoryID passed as input to Index GET controller).
Also, it has a "Add" button below list which calls Category Details (GET) controller (passing categoryID to controller) which displays a form with Text box and button to add new category.
Once user enters category Details and press submit, Details (POST) controller is called which saves data and should redirect user back to page from where it was called.
This user control (razor file) can be used multiple times on same page.
Queries
1) What is best approach to integrate such a control in page views such that form in every user control is self contained and doesn't conflicts with other instances of same user control in same page?
2) I tried Html.RenderAction("Index","Category",new {categoryName = "toys"})
This works well in displaying category and clicking on Add button does takes user to "Add a new category" page. Problem is, what code should I write such that I can take user back to the same view page, where the user control was embedded (even better if I can scroll window to the position where control was placed)?
thanks!
When Data is posted in a partial view to the corresponding Action , It has no context of the main view/action. So we can post data to the main action so that modelstate is preserved and can be validated.
But if you want to post data to the partial view/action, we can redirect to main view/action post product is added.(But if some invalid data is entered, we cannot display any validation error)
[HttpPost]
public PartialViewResult AddProduct(string productId,string returnUrl)
{
//Add product
return Redirect(returnUrl);
}
What you are looking for is a partial view, namely an editor template.
In your Views folder, create a Shared folder and inside that create an EditorTemplates folder. From there create a strongly typed partial view named the same as the part of the model.
Then on your main view call EditorFor.

How to show validation messages in MVC?

When a user tries to click:
Save
and they have entered in some invalid data, i want to notify them. This can be with methods such as:
directing their attention to the thing that needs their attention with a balloon hint
automatically dropping down a combo-box
triggering an animation
showing a modal dialog box
etc
What is the mechanism where a controller tells the view to show a validation message for some controls, given that different views have different notification methods?
p.s. the controller doesn't know the order that controls are physically arranged in the view (e.g. LTR locale wants to notify the user in a top-down-left-to-right visual order, while RTL locale wants to notify the user in a bottom-up-right-to-left order)
The controller can add a Validation object to the Model, which can contain the names of the fields which were invalid, specific validation messages, etc.
The View can then choose to render this Validation object however it wishes: by highlighting the incorrect fields, animating something, showing a modal dialog, etc.
If you are using ASP.Net MVC 2.0, check out this post by Scott Gu, although some of this will apply for ASP.Net MVC 1.0 as well.

Resources