How to stop knockout.js bindings evaluating on child elements - data-binding

Using knockout, when you call ko.applyBinding(viewModel, "divId") it does a recursive binding down through the children of the element you bound to ("divId"). I would like to stop this evaluation at a child node. Is there a way to do this?
the reason why...
I would like to bind the entire page to a navigation view model, this will handle basic layout and ...smile... navigation. On the various pages I would like to bind certain regions to different view models that are not properties of the navigation view model. At the moment if I do this I get "unable to parse binding" errors as the navigation view model does not have the required properties. If I could stop the binding walking down the dom, I could just bind these items separately.

There are several ways that you can go on this one. Typically, you would add multiple "sub" view models to a main view model and then use the with binding on the various areas with the actual view models to bind against them.
It is possible to technically do what you are after. You can create a custom binding that tells KO that it will handle binding the children itself. It would look like:
ko.bindingHandlers.stopBindings = {
init: function() {
return { controlsDescendantBindings: true };
}
};
When you place this on an element, then KO will ignore the children. Then, you could call ko.applyBindings on a child of this element with a different view model.
Sample: http://jsfiddle.net/rniemeyer/tWJxh/
Typically though, you would use multiple view models underneath a main view model using the with binding.

One way I have done this is to create a section for the navigation (or just a ) and bind the navVM to it. Then create another section for the content and bind the contentVM to it. That way there is no conflict and its all very separated.
<body>
<div id="navSection">
</div>
<div id="contentSection">
</div>
</body>
Then do ko.applyBinding(navVM, "navSection") and ko.applyBinding(contentVM, "contentSection")

Related

How do I edit variables and update content of a view component using a button within the same component?

Summary: I have a view component with buttons which need to be able to change the details displayed in the rest of the component on click, but i can't figure out how to update the components content and data using an element within the component.
I am using asp.net razor pages to make a simple UI which displays various info grabbed from a JSON file, no database connection or POST functionality necessary.
I want the block of html that displays the data to be a reusable component, so i don't have to rewrite it every time i want to show a different entry in the file. From my research, there are a few options: HTML components, tag helpers, razor components, partial views, and view components. I chose to use a view component since the other options all seemed either outdated or not capable enough to achieve what i wanted. That is, with the exception of razor components, which require blazor to function fully which would also require me to learn a whole new framework and retrofit my program to work for it.
My view component functions to the point where i can invoke it from Index.cs and the component shows all the data from the first log in the list, as desired.
My intention: the default entryNo value is 0, so the component shows the title and date from the first log entry. When a user clicks the "Next" button (inside the component), entryNo becomes 1, and the component shows the title and date of the second entry in the log file.
ViewComponent.cshtml:
#model FullLog
#{ int entryIndLocal = 0; }
<div>
<div>#Model[entryNo].Title</div>
<div>#Model[entryNo].Date</div>
<button onclick={entryNo++}>Next</button>
</div>
What i've tried:
Setting the entryNo value in the view's .cs file and including a function to increment that value when called. I couldn't figure out how to call the function from the cshtml.
Initialising the entryNo variable from within the cshtml file, with the intention of the adding onclick={#entryNo++}. This didn't work either.

How to inject a child component into a razor generic component like react.js

I would like to know if it is possible to create components (Razor / Asp.NET) like the react style. I'll illustrate:
<GenericDadContainer>
<ChildComponentDinamic />
</GenericDadContainer>
I want to do this so that my parent containers have dynamicity. They will serve only as containers, and your children need to be dynamic regardless of their models.
If possible I would also like to know if in this context it would be possible to pass parameters to the same besides the child itself.
I understand little of Razor, and I didn't find anything from the internet on a way to reuse the layout better.
Not exactly the same style, but the same idea: in Razor, you can use the so-called "partial views" to divide your page up into "components", and yes, you can pass data to a partial view.
Here is a mini-example:
<div class="container">
#Html.Partial("view-name-here", model)
</div>
The model variable could be any object you choose.
Read up on partial views in ASP.NET/MVC, for example here.

How to move components around

I'm using the 0.4.0 branch for the components as HTML files functionality. I'm trying to do the following: I have a component that controls the layout of a page. This component has some subcomponents as an array and displays them on different parts of the page based on some data in the subcomponent. Something akin to this (due to layout restrictions they have to be in different parts of the page):
<div id="section1">
<h1> Section 1 </h1>
{{# subcomponents}}
{{#isflagsection1(flag)}}
<subcomponent flag={{flag}}/>
{{/isflag}}
{{/subcomponents}}
</div>
<div id="section2">
<h1> Section 2 </h1>
{{# subcomponents}}
{{#isflagsection2(flag)}}
<subcomponent flag={{flag}}/>
{{/isflag}}
{{/subcomponents}}
</div>
<div id="section3">
<h1> Section 3 </h1>
{{# subcomponents}}
{{#isflagsection3(flag)}}
<subcomponent flag={{flag}}/>
{{/isflag}}
{{/subcomponents}}
</div>
The flag is updated from controls within each component. this works great (the DOM is refreshed each time I modify the flag) except for one issue. Instead of performing a move, the subcomponent is recreated every time the flag changes, e.g. it's destroyed and created a new. This is unfortunate for my use case because of two reasons:
The subcomponent has a rather heavy creation cost (specially in mobile) since it performs some graphics work.
The subcomponent stores some private data (a
history of changes made to the model) that either a) gets lost when
it's moved along to another section or b) has to be stored in the
top component polluting it's data model.
So what I would like to know is, is there a way to "move" the component without deleting/recreating it?
Regards,
V. SeguĂ­
Yes - every Ractive instance has two methods that allow you to do this: ractive.detach() and ractive.insert(). Unfortunately the documentation is currently lacking, but here's how you use it:
// remove the instance from the DOM, and store a document
// fragment with the contents
docFrag = ractive.detach();
// insert the instance into the container element, immediately
// before nodeToInsertBefore (the second argument is optional -
// if absent or `null` it means 'insert at end of container'
ractive.insert( container, nodeToInsertBefore );
If you're removing the instance and immediately reinserting it, there's no need to detach it first - you can just do ractive.insert(). The arguments can be DOM nodes, but they can also be CSS selectors or the IDs of elements.
Here'a a JSFiddle demonstrating: http://jsfiddle.net/rich_harris/Uv8WJ/
You can also do this with inline components (i.e. <subcomponent/> as opposed to new Subcomponent(). In this JSFiddle, we're using ractive.findComponent('subcomponent') method to get a reference to the instance: http://jsfiddle.net/rich_harris/f28t5/.

Validation while rendering multiple partial views

I have multiple views/models that are being looped into the main view. I load them via #Html.Partial()...These views/models are basically form elements with certain properties...Unfortunately I soon found out that only the first of each type of view/model is validated. I tried moving the fields around and only the first of each kind would validate.
My partial views look something like this:
#Html.DropDownListFor(model=>model.dropdownVal,Model.SelectItems,new { id=Model.FieldID, Name = Model.FieldID })
I looked at the HTML rendered, and it seems that the validation tags like "data-val" are not applied...
Any ideas would be greatly appreciated!
Add the following at the top of your partials to trick ASP.NET MVC into thinking that the helpers are used inside a form and generate the proper data-val attributes:
#{
this.ViewContext.FormContext = new FormContext();
}
Basically the Html.* helpers are generating data-val clients side validation attributes only if they are placed inside an Html.BeginForm. Except that in your case I guess that this Html.BeginForm is in your parent view and not inside the partial, so the #Html.DropDownListFor doesn't emit any validation attributes. By setting the current FormContext to a new instance in the partial as shown previously, the helper will generate the proper client side validation attributes on the corresponding input field.

MVC - How best to organize commonly used drop-down lists in many views

I am trying to understand how best to organize some common Dropdown lists used in several views (some are cascading)
Is it best to create
a single \Models\CommonQueries
then create a webservice for each dropdown used in cascading situation
then have a single controller that contains actions for each dropdowns
This way I can follow DRY principle and not repeat the dropdown logics since they are used in various views.
Much Thanks and Regards for reading my question and taking the your time.
+ab
When you say your dropdowns are used in several views, do you still consider these dropdowns as part of the view that is rendering them? If so, I think using a custom HTML helper or a partial view (ascx) is appropriate. Then, like you suggest, you can populate the data for the dropdowns using a common service from your domain layer. I think that is a very reasonable approach.
However, if you feel the dropdowns are somewhat external/unrelated to the view, then you might find that using Html.RenderAction() gives you a much cleaner result. Using Html.RenderAction(), you can output the result of an Action method directly into any other view. Therefore, you can create 1 controller with the necessary Action method(s) to populate those dropdowns. For example, let say you have a view with roughly something like:
<div>
<div id="coreView1">
<!-- some view code here -->
</div>
</div>
<div id="commonDropdowns">
<% Html.RenderAction("Create", "Dropdown"); %>
</div>
where Create is the name of your method in the DropdownController.
For example:
public class DropdownController : Controller
{
public ViewResult Create()
{
// do stuff here to create the ViewResult of the common Dropdowns
}
}
Note: Some people dislike this approach as it doesn't fit the typical MVC seperation of concerns. However, it can be a really great fit for some cases.
Hope one of these approaches can help.

Resources