How to fit MVC Controls Toolkit into my existing solution.

Feb 27, 2013 at 2:21 PM
Edited Feb 27, 2013 at 2:41 PM
I've been trying to use MVC Control Toolkit inside my existing solution, and having a very hard time with it. The problem stems around the fact that the existing solution has an SPA infrastructure, so it doesn't really mimic any of your sample application.

All I want to do is create a read-only, sortable, filterable grid with odata/ajax data source.

Because I'm plugging this into an existing SP project, I have the following limitations:

1) I already have knockout included elsewhere, so I can't use the MVCCT knockout.all-2.2.5.min.js.
2) I already bind KO at the root DOM level, so I can't rebind KO at the grid level.
3) The view that the grid exists on is surrounded by a KO "if" block, so it the HTML will not be included in the DOM until KO says that view should be visible. I'm pretty sure this means any inline javascript will executed on the original grid DOM, and not on the new grid DOM created by KO when the "if" block is true.
4) Because of the SPA infrastructure, the view containing the grid is a partial view.

So I believe I have the following requirements of of MVCCT:
1) Any client-side model needs to be assigned to a property of my existing root-level model. (e.g. myrootvm.mygridpage.gridvm(vmcreatedbymvcct).
2) Any KO binding done by MVCCT needs to bind to the property of my existing root-level model (from #1: myrootvm.mygridpage.gridvm()).
3) Any inline script generated by MVCCT needs to be "executed" on the DOM delay-created by KO.


That said, I'm trying to approach this in stages, since I'm having so much trouble.
First: I'd like to create the read-only grid without sorting or filtering.
Second: once that's working, then I can add filtering.
Third: once that's working then I can add sorting.

So my question is: Can you provide me with some simple code to get just the read-only grid (#1, above) working without sorting or filtering? I can't seem to find a way to get MVCCT to meet any of the 3 requirements, above.
Coordinator
Feb 28, 2013 at 5:15 PM
1) I already have knockout included elsewhere, so I can't use the MVCCT knockout.all-2.2.5.min.js.
No problem for this. knockout.all-2.2.5.min.js.min contains 3 file (including also knockout.js) as explained here:

knockout.all-x.x.x.min.js includes, knockout-2.0.0.js, knockout.mapping-2.0.0.js, and MvcControlToolkit.Bindings-x.x.x.js minimized with YUI compressor. If you would like to upgrade to a newer version of the knockout you can build yourself this file.

So just prepare a minimized js file with the other two files. If the problem is you would like to use knockout 2.2 consider it will be included in the 2.4 release of the toolkit that will be released in about a week.
3) The view that the grid exists on is surrounded by a KO "if" block, so it the HTML will not be included in the DOM until KO
This is not a problem, in general, Knockout grid are implemented with the template binding so they can be nested with other knockout constructs. Moreover Mvc Controls Toolkit contains enhancement fo all knockout control flow bindings.

2) I already bind KO at the root DOM level, so I can't rebind KO at the grid level.
If you already have a ViewModel in the client side you cannot use Client Blocks, since they takes care also of rendering the ViewModel , but you can define manually your binding with an IBindingsBuilder interface you get somehway(I will explain how after you clarify me some points). This way you may benefit of all enhancements included by mvc controls toolkit such as validation attributes taken into account, strongly typed value binding etc.

4) Because of the SPA infrastructure, the view containing the grid is a partial view.
Not sure what you mean with this. If you mean you render a partial view withing scripts tags of type text/template, please note what follows SCRIPT CANNOT BE NESTED. This mean your partial view CANOOT CONTAIN ANY javascript or further templates! Now templaters rendered by the Mvc Controls Toolkit encode js script to make possible their insertion within a script of the type text/template. Then the Mvc Controls toolkit decode them when it "prepare the templates".
However to get this service done you must render your partial view template with the Mvc Controls Toolkit facilities. IN ANY CASE your partial view CANNOT CONTAIN FURTHER TEMPLATES nested into it.
Let me know more infos about how your code is organize, in particular about you point 4 and about the problem I pointed out. Then I will try to sketch a solution suitable for you.
Mar 14, 2013 at 12:01 AM
So since I can't use Client Blocks, does that mean I can't use the Grid control?
Coordinator
Mar 14, 2013 at 1:50 AM
Client Blocks enhance Ko in Several ways and Allow a Good match With The Server side Mvc Controllers And models. Updates manager And Retrieval Managers That Are the Main tools To implement a Filte/sort/page Grid That Is Able to seng Just The change Set To the server Relies on the Enhancements Added by Clients blocks.
You Can Still Implement A Ko grid But Then You Have To Implement Yourself All Logics To Filter Page and Sort Data And To Handle Validation Errors. Then You have to Extract changes to Pass To The Database Once The Controller Receives the client side Viemodel.

There are Other Frameworks That May Help you like Breeze...but Also they Have problems to fit into An An Existing solution.
If You Post Some Code I May suggest how To proceed. Maybe You can Use Client Blocks With your projects with minimal changes....
Mar 15, 2013 at 5:58 PM
Edited Mar 15, 2013 at 6:02 PM
FYI, I was able to get Client Blocks to work inside my application, but it required me to use the MVCCT source code instead of the nuget package and make some changes.

1) I had to add parameters to the Client Block code to force it to not automatically apply the bindings.
2) In the control helpers (e.g. ClientPager contructor, ClientPager.Buton...), I had to add parameters and add methods and modify some methods to allow me to customize the generated HTML.
3) Had to customize the code that the nuget package added to App_Start.cs.

After I did all this, I added some javascript to take what the MVCCT generated and put it into my global client-side view model.

I'm still testing, but it appears this solution will work if I force it enough. I've still got to figure out the problem that nothing works if a KO "if" binding removes the Grid from the DOM and then re-adds it.

The biggest complaint I have in all this (IMHO) is that MVCCT is pretty hard-coded with a lot of the HTML/javascript that gets used for the different parts of the Grid. If you could either allow more templates to be passed in (like you do with the ClientBlockRepeater, which is awesome), or else structure things a bit differently so that I can write my own HTML and then just attach javascript to it using MVCCT, that would be much better.

To take that a step further, in order to use the Grid's filtering, I'm required to add a checkbox that shows/hides the filter and I'm required to add another method call which initialized the filter show/hide. Additionally, without a lot of customization to the MVCCT code, I can't create the (1), (2), (3), etc. paging buttons on my own.

I could go on, but the point is that it all seems a little too hard-coded.

My second biggest complaint is that the MVCCT javascript libraries are all added to the global scope, which isn't a very modern way to add javascript libraries (e.g. jquery-related stuff ever only adds 1? variable to global scope).

My third complaint is that while trying to get the parts of the Grid working, any problems I had were usually caused by naming things incorrectly or passing in a wrong string.


All that being said, I'll end on a good note! The templating/client block stuff is great!

So after my experimenting, what I'll probably end up doing long-term is just using the MVCCT templating and client block code, but ditch the Grid code in favor of something else.
Coordinator
Mar 16, 2013 at 11:35 AM
First of all some words on the problem you had with the nuget package.
The error message you get is due to a string length validation rules that is applied twice on your textbox. Resulting on a double application of the data-length Html5
attribute. This is due, probably, to the fact that you are using fluent validation, but at the same time you (you....or some scaffolding egine) applies a data annotations on the same property. Result, the string length validation rule is applied twice. Once with data annotations anth the other with fluent validation. PLEASE LET ME KNOW ABOUT THIS, because if there is an issue I need to chasnge the Nuget package (though I dont think because none else had the same problem)

Second, about disabling automating binding. While some lower level Api allows this I have chosen to force users of ClientBlocks to keep it enabled. The reason is simple some features such as the pager ...and other need such binfings to work properly. Now you appear to be smart enough to overcome similar problems....but the average use is not.....so I will not give the possibility to disable automatic binding. HOWEVER, you may disable automatic binding on each single input field by appling to it the data-nobinding='true' Html5 attribute. This way the developer may prevent automatic binding on the input field he defines but cannot prevent it on other input fields handled automatically by the client blocks engine.

About your other complaint, what I will do is mainly to improve documentation, that was built incrementally while new features were added to the Mvc Controls Toolkit, and now it appears a little bit confusing. Actually several stuffs you complainted can be solved easily, but the way to solve is either absent or hard to find in the documentation.

For instance, a lot of js code automatically rendered by the Mvc Controls Toolkit engine, put js data structure into some vars. However such vars dont need to be simple js vars lost in global scope(though they cannot be within the scope of a function since they must be globally accessible).... For instance when you specify the name of the var where to put the clientside viewmodel you may specify something like: MyNameSpace.MyClientViewModel. In such case the engine will add the MyClientViewModel property to the preexisting MyNameSpace(that ou maight have defined in your js files). If MyNamespace doesnt exists it is created. This is written in a single ...lost place in the doc but not stressed enough.

About the several parts needed to build the working grid...it is true for a beginner it is quite hard to assemble it. However, they may be customized as you like.
For instance the sort buttons maybe images, links, etc. Moreover you may also define custom sortbuttons...but then you must take care of enforcing the name convention that ensures everything will work.

About the filter....No you are not forced to use a checkbox and select. What the the DataFilterClauseFor do is just creatong an HtmlHelper specific for a ViewModel with three properties the Search field, a boolean enable field, and a condition select property. That said....you are not forced to render them as I have done in the examples. For instance if you dont want the checkbox, you may just render the boolean in an hidden field where you put the constant True value...The same apply to the condition selection field. Moreover, if you dont want the user selects the filter orperator and enabls the filter condition but just want a fixed predefined filter you may just encode yourself the filter conditions into the jsQueryable you use to send the query to the server(More details on the specific discussion you opened on this subject)

That said stay tuned, nex week I will publish tutorials and video of the Release Candidate of the Data Moving Plugin of the Mvc Controls Toolkit that contains completely out-of-the box controls. In this case you dont need to do any job to have filtering, paging, and sorting....just enabling them in a fluent interface....with something like QueryResolver(true, true,....) where you specify the services you need....Every button can be customized with a custom icon or with custom Html. The only requirement of a button is to have an Html5 attribute that specifies the code of the operation associated to the button (very, very easy to use and customize).
everything is built on top of the Mvc Controls Toolkit....that allows this flexibility (not well documented...but it exists:) )

In the next 30 days we will produce the doc for the Data Moving Plugin that should be available within one month and we will take advantage of this for re-engineering the whole documentation of the Mvc Controls Toolkit.
Coordinator
Mar 16, 2013 at 12:20 PM
About the problem you had with the knockout if statement. Try to substitute it with the _if helper.
Maybe the problem is the javascript code that is rendered withing the if scope. The _if helper do the same job of the ko if helper but the manage everything in such a way that all templates and javascript are cached and rendered out of the _if scope.

However, it is worth to point out that the if statement doesnt simply hide and show the Html but it destry and create it again. So it works ONLY IF THE WHOLE HTML can be created properly with the help of KO bindings. Thus if the body of the if contains infos that are not encoded in the clientside viewmodel and properly bound to the Html with ko bindings, such information will be lost when destroing and creating agin the if body.