Giter Club home page Giter Club logo

knockout-mvc's People

Contributors

andreyakinshin avatar diegohoyos avatar drazmazen avatar drgrieve avatar drvic10k avatar hazzik avatar larsw avatar lukasz-lysik avatar maxkoryukov avatar plmeister avatar rchcomm avatar rnikitin avatar robbittner avatar vfportero avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

knockout-mvc's Issues

An item with the same key has already been added.

Don't know if this should be regarded as a bug, but if the viewmodel contains two properties with the same name, but in different case, when the modelbinder adds propertynames, this error is thrown.
If this will not be supported, maby a little mer explanatory exception should be thrown, so one knows that it's actually the vm that contains an error, and not the markup (as I thought).

IKnockoutContext.GetIndex() not supported in complex binding expressions

The method KnockoutExpressionConverter.VisitMethodCall(MethodCallExpression) needs to check if the called method is IKnockoutContext.GetIndex(), compile it to a lambda, execute it to retrieve the index binding, and return it from the visitor method. This should allow complex binding expressions to support GetIndex().

Cannot create computed property with bool return type

For some reason any computed properties that return bool cause the ko.Initialize() method call to fail. For example this fails:

[Computed]
public bool HasExpirationDate { get { return true; } }

This will cause this call to fail:

@ko.Initialize(Model)

With the following error:

No coercion operator is defined between types 'System.Int32' and 'System.Boolean'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: No coercion operator is defined between types 'System.Int32' and 'System.Boolean'.

Source Error:

Line 7: {
Line 8: @Scripts.Render("~/bundles/scripts/datepicker")
Line 9: @ko.Initialize(Model)
Line 10:
Line 11: <script>

Source File: c:\Development\Projects\Base House Contracting\Dev\Website\Views\TradeReview\Index.cshtml Line: 9

Stack Trace:

[InvalidOperationException: No coercion operator is defined between types 'System.Int32' and 'System.Boolean'.]
System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method) +6156301
DelegateDecompiler.MethodBodyDecompiler.Decompile() +297
DelegateDecompiler.Cache2.GetOrAdd(TKey key, Func2 func) +247
DelegateDecompiler.DecompileExtensions.Decompile(MethodInfo method) +127
DelegateDecompiler.DecompileExpressionVisitor.Decompile(MethodInfo method, Expression instance, IList1 arguments) +36 PerpetuumSoft.Knockout.KnockoutJsModelBuilder.AddComputedToModel(Type modelType, Object model, String modelName) +321 PerpetuumSoft.Knockout.KnockoutContext1.GetInitializeData(TModel model, Boolean needBinding) +526
PerpetuumSoft.Knockout.KnockoutContext1.Initialize(TModel model) +14 ASP.<>c__DisplayClass4.<Execute>b__2() in c:\Development\Projects\Base House Contracting\Dev\Website\Views\TradeReview\Index.cshtml:9 System.Web.WebPages.<>c__DisplayClassb.<RenderSection>b__9(TextWriter tw) +289 System.Web.WebPages.WebPageBase.Write(HelperResult result) +89 ASP._Page_Views_Shared__Layout_cshtml.Execute() in c:\Development\Projects\Base House Contracting\Dev\Website\Views\Shared\_Layout.cshtml:74 System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +280 System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +125 System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +196 System.Web.WebPages.WebPageBase.Write(HelperResult result) +89 System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action1 body) +233
System.Web.WebPages.WebPageBase.PopContext() +291
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +380
System.Web.Mvc.<>c__DisplayClass1a.b__17() +33
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +613 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +613
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +613 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList1 filters, ActionResult actionResult) +263
System.Web.Mvc.Async.<>c__DisplayClass25.b__22(IAsyncResult asyncResult) +240
System.Web.Mvc.<>c__DisplayClass1d.b__18(IAsyncResult asyncResult) +28
System.Web.Mvc.Async.<>c__DisplayClass4.b__3(IAsyncResult ar) +15
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
System.Web.Mvc.Async.<>c__DisplayClass4.b__3(IAsyncResult ar) +15
System.Web.Mvc.<>c__DisplayClass8.b__3(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c__DisplayClass4.b__3(IAsyncResult ar) +15
System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +282

A bug or my fault?

View:

@using PerpetuumSoft.Knockout

@model Smev.Astd.DataModel.Context

@{ var ko = Html.CreateKnockoutContext(); }

<fieldset>
    <legend>Изменение контекстного справочника</legend>
    <br />
    @using (var contextDictionary = ko.Foreach(m => m.Dictionaries))
    {
        @ko.Html.HyperlinkButton("[x]", "RemoveDictFromContext", "ContextDictionaryController", new { dictIndex = contextDictionary.GetIndex() })
        <table>
            <tr>
                <td>Идентификатор:</td>
                <td>
                    @contextDictionary.Html.TextBox(m => m.Name)
                </td>
            </tr>
            <tr>
                <td>Отображаемое название:</td>
                <td>
                    @contextDictionary.Html.TextBox(m => m.DisplayName)
                </td>
            </tr>
        </table>
        <br />
        <div>
            <table>
                <tr>
                    <th />
                    <th>Value</th>
                    @using (var key = contextDictionary.Foreach(k => k.Keys))
                    {
                        <th>
                            @key.Html.TextBox(k => k)
                            @ko.Html.HyperlinkButton("[x]", "DeleteKey", "ContextDictionaryController", new { dictIndex = contextDictionary.GetIndex(), keyIndex = key.GetIndex() })
                        </th>
                    }
                    <th>
                        @ko.Html.HyperlinkButton("[+]", "AddKey", "ContextDictionaryController", new { dictIndex = contextDictionary.GetIndex() })
                    </th>
                </tr>
                <tbody>
                    @using (var row = contextDictionary.Foreach(k => k.Rows))
                    {
                        <tr>
                            <td>
                                @ko.Html.HyperlinkButton("Удалить строку", "RemoveRow", "ContextDictionaryController", new { dictIndex = contextDictionary.GetIndex(), rowIndex = row.GetIndex() })
                            </td>
                            <td>
                                @row.Html.TextBox(r => r.Value)
                            </td>

                            @using (var entry = row.Foreach(e => e.Entryes))
                            {
                                <td>
                                    @entry.Html.TextBox(e => e)
                                </td>
                            }
                        </tr>
                    }
                </tbody>
                @ko.Html.HyperlinkButton("[+]", "AddRow", "ContextDictionaryController", new { dictIndex = contextDictionary.GetIndex() })
            </table>
        </div>
        <br />
    }
    @ko.Html.Button("Сохранить", "Save", "ContextDictionaryController").Enable(m => m.Dictionaries.Count > 0)
</fieldset>

@ko.Apply(Model)

Generated HTML(this part):

<fieldset>
    <legend>Изменение контекстного справочника</legend>
    <br>
<!-- ko foreach: Dictionaries -->
<a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveDictFromContext?dictIndex='+$index()+'');}" href="#">[x]</a>        <table>
            <tbody><tr>
                <td>Идентификатор:</td>
                <td>
                    <input data-bind="value : Name">
                </td>
            </tr>
            <tr>
                <td>Отображаемое название:</td>
                <td>
                    <input data-bind="value : DisplayName">
                </td>
            </tr>
        </tbody></table>
        <br>
        <div>
            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/AddRow?dictIndex='+$index()+'');}" href="#">[+]</a><table>
                <tbody><tr>
                    <th>
                    </th><th>Value</th>
<!-- ko foreach: Keys -->
                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>

                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>

                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>

                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>

                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>

                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>

                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>

                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>

                        <th>
                            <input data-bind="value : $data">
                            <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/DeleteKey?dictIndex='+$parentContext.$index()+'&amp;keyIndex='+$index()+'');}" href="#">[x]</a>
                        </th>
<!-- /ko -->
                    <th>
                        <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/AddKey?dictIndex='+$index()+'');}" href="#">[+]</a>
                    </th>
                </tr>
                </tbody><tbody>
<!-- ko foreach: Rows -->
                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>

                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>

                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>

                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>

                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>

                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>

                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>

                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>

                        <tr>
                            <td>
                                <a data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/RemoveRow?dictIndex='+$parentContext.$index()+'&amp;rowIndex='+$index()+'');}" href="#">Удалить строку</a>
                            </td>
                            <td>
                                <input data-bind="value : Value">
                            </td>

<!-- ko foreach: Entryes -->
                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>

                                <td>
                                    <input data-bind="value : $data">
                                </td>
<!-- /ko -->
                        </tr>
<!-- /ko -->
                </tbody>

            </table>
        </div>
        <br>
<!-- /ko -->
    <button data-bind="click : function() {executeOnServer(viewModel, '/ContextDictionaryController/Save');},enable : Dictionaries().length&gt;0">Сохранить</button>
</fieldset>

MVC 6?

Are there any plans to support MVC 6?

data-bind attribute for Nested object is invalid

For the following JSON:

{"ParentTitle":"Fred","Belongings":{"Title":"My stuff","Things":[{"Description":"Shoe","Amount":123},{"Description":"Hat","Amount":456}],"Summary":"I have lots"}}

The 'Belongings' object is a nested object (and not an array). The ko.mapping.fromJS(viewModelJs) does not make the Belongings object an observable so it's properties should be accessed as:

Belongings.Title

but the ko.Html.TextBox (and the ForEach functionality) create:

Belongings().Title

This then causes an exception in the call to:

ko.applyBindings(viewModel);

because it can't find Belongings().Title

I've manually created html without the () and the bindings work correctly.

Is it possible to fix do a urgent fix for this problem?

Thanks,
P

HTML injection in KnockoutContext.Apply(Model) and Initialize(Model)

Example form to reproduce:

@model WebApplication.Models.DefaultModel
@{
    var ko = new KnockoutContext<WebApplication.Models.DefaultModel>(ViewContext);
}

<form>
    @ko.Html.TextBox(m => m.Foo)
    @ko.Html.Span(m => m.Foo)
    <button type="submit">Send</button>
</form>

@ko.Apply(Model)

model:

public class DefaultModel
{
    public string Foo { get; set; }
}

action:

[ValidateInput(false)] // turn off XSS protection in ASP.NET
public ActionResult Index(Models.DefaultModel model)
{
    Response.AddHeader("X-XSS-Protection", "0"); // turn off XSS protection in browser

    return View(model ?? new Models.DefaultModel());
}

Steps to reproduce:

  1. Type </script><script>alert('XSS');</script><script> into textbox
  2. press Enter

Vulnerable line:

sb.AppendLine(string.Format("var {0}Js = {1};", ViewModelName, json));

Possible solution:

sb.AppendLine(string.Format("var {0}Js = {1};", ViewModelName, json.Replace("<", "\\u003c")));

Workaround:

@{ 
    var script = ko.Apply(Model).ToString();
    var p1 = script.IndexOf('>');
    var p2 = script.LastIndexOf('<');
    WriteLiteral(script.Substring(0, p1) + script.Substring(p1, p2 - p1).Replace("<", "\\u003c") + script.Substring(p2));
}

.Bind.Custom does not accept an expression

Is it possible to add an overload: KnockoutBinding.Custom that accepts an expression?

i.e.

public KnockoutBinding Custom(string name, Expression<Func<TModel, object>> binding)
{
Items.Add(new KnockoutBindingItem<TModel, object> { Name = name, Expression = binding });
return this;
}

Click Binding only make server sides call

It could be useful a binding method to map the following cases:

data-bind="click:doSomethingOnViewModel"
data-bind="click:doSomethingOnViewModel.bind($data, 'parameter1')"

where doSomethingOnViewModel is a model's function.

Cannot use Regex in Computed observable

I have a computed property in my viewmodel like this:

  [Computed]
  public int PasswordScore
  {
      get
      {
          var strongRegex = new Regex("^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$");
          var mediumRegex =
              new Regex("^(?=.{7,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$");
          //var enoughRegex = new Regex("(?=.{6,}).*");
          if (NewPassword.Length < 1)
              return 0;
          if (NewPassword .Length < 6)
              return 1;
          if (strongRegex.Match(NewPassword).Success)
              return 4;

          return mediumRegex.Match(NewPassword ).Success ? 3: 1;

      }
  }

Also I have in my View the following statement:

@ko.Html.Span(m => m.PasswordScore)

I get the error NotSupportedException. This exception happens in VisitMethodCall(MethodCallExpression m).

The state of the variables when reaching that function is:

?m.Method
{System.Text.RegularExpressions.Match Match(System.String)}
[System.Reflection.RuntimeMethodInfo]: {System.Text.RegularExpressions.Match Match(System.String)}
base {System.Reflection.MethodBase}: {System.Text.RegularExpressions.Match Match(System.String)}
MemberType: Method
ReturnParameter: {System.Text.RegularExpressions.Match }
ReturnType: {Name = "Match" FullName = "System.Text.RegularExpressions.Match"}
ReturnTypeCustomAttributes: {System.Text.RegularExpressions.Match }
?m.Object
{HelloWorldModel.expression}
CanReduce: false
DebugView: "KnockoutMvcDemo.Models.HelloWorldModel.expression"
Expression: null
Member: {System.Text.RegularExpressions.Regex expression}
NodeType: MemberAccess
Type: {Name = "Regex" FullName = "System.Text.RegularExpressions.Regex"}

KnockoutUtilities.ConvertData ignore JsonIgnore Attribute

I use JsonIgnore attribute to avoid circular references in Json serialization of entity framework classes. The problem is in KnockoutUtilities.ConvertData method because ignore this attribute when explore properties using reflection. This cause stack overflow exception when explore recursive circular references between entity framework objects.

jQuery 2.1.1 NuGet dependency - why?

I was wondering if there was a possibility of lowering the version requirement for jQuery, which is currently 2.1.1 in the knockout-mvc NuGet package. Most applications I write (along with many people in the community) need to support IE8 (unfortunately) in which using jQuery 1.11.2 (or any 1.x release) is the only option. Is there a specific feature of knockout-mvc that requires the newer 2.x jQuery? Is it possible to make the requirement 1.11.2 instead?

'System.NotSupportedException in Computed

I have this computed property
[Computed]
public decimal CostoCalcolato
{
get
{
return Fornitore + Facon + Tessuto + Fodera + Accessori + TrasportoInterno + TrasportoCliente + TrasportoAccessori + Dogana + ImportoFinanziamento + Varie;
}
}

in my model, all properties used in the get method are decimal, the error i get is: NotSupportedException();
In the basecode it comes from VisitMethodCall(MethodCallExpression m) in KnockouExpressionConverter.cs.

The Methodname i get is op_Addition that is not supported.

I'm missing something?

Access current record in Foreach

Background Information:

I am trying to pass in the current collection iteration's model value as a parameter to an action method in a controller.

More Details:

While working with a collection, I am iterating over the collection with the following code snippet:

@using (var players = ko.Foreach(x => x.BenchPlayers))
{
    <tr>
        <td @players.Bind.Text(x => x.Name) class="vert-align"></td>
        ...
        <td class="vert-align">@ko.Html.Button("Put in Game", "PutInGame", "Home", new { player = players.Model }, new { @class = "btn btn-primary" })</td>
    </tr>
}

I am attempting to access the current iteration's Model value, but I am unsuccessful. The Model property appears to just be a new instance of the class it represents.

Is there a way to access the current iteration of the foreach loop, for the purposes of passing it to the routeValues collection, for use in the action method in the controller? If need be, I can just use a property of the object, rather than the entire object, but I'd rather use the entire object.

ForEach method with IEnumerable<TItem>

For "ForEach" method of "KnockoutContext" class, the use of IEnumerable for the "binding" parameter would be useful to avoid constrain on the ViewModel class.

Is it feasible? Changing the code unit tests in the solution always succeed.

Posting data with redirecting

In a situation, when you want to post data and then redirect to some other action, this is not possible with the auto-generated Button, because it expects the model as a return value.
I ended up using the raw HTML with event hooked on a modified post function that receives url in response and then redirects to that url on success.
But it would be nice to either have the possibility to change the onclick function used in auto-generated Button, or have a different method for creating Button with regirecting.

Setting readonly property

In method ConvertData, property.SetValue(data, value, null); tries to set value for a readonly property. This doesn't throw an exception on .NET 4.0, but on .NET 4.5 it does.

The obvious solution is checking if you can wtite to the property:
if (property.CanWrite) { property.SetValue(data, value, null); }

This seems to be critical bug, I wonder if anyone else encountered this.

Unobtrusive Validation

It would be nice if this bound to Unobtrusive validation easy... Which I was able to add pretty easy off the base htmlHelper.

public static class KnockoutEditorExtensions
    {
        public static MvcHtmlString KnockoutTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string binding)
        {
            return html.TextBoxFor(expression, null, new { @data_bind = binding + ", attr: { 'name': '" + html.NameFor(expression) + "_' + $index() }" });
        }

        public static MvcHtmlString KnockoutValidationMessageFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
        {
            return html.ValidationMessageFor(expression, null, new { @data_bind = "attr: { 'data-valmsg-for': '" + html.NameFor(expression) + "_' + $index() }" });
        }
    }

NODE: Some of the code is referenced from here https://github.com/tathamoddie/KnockoutJS-Demos/issues

Lazy Load w/ ko.Html.Button

It seems that after lazy load runs it stores the value of view model internal to the $.get, so when an action button is called it has no idea what "viewModel" is, so it throws a javascript error.

EX:

a data-bind="click : function() {executeOnServer(viewModel, '/api/Address/322');}" a data-bind="click : function() {executeOnServer(viewModel, '/api/Address/322');}"
<script type="text/javascript"> 

$(document).ready(function() {$.ajax({ url: '/api/Address/1', type: 'POST', success: function (data) {
var viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
}, error: function (error) { alert('There was an error posting the data to the server: ' + error.responseText); } });
});</script>

Redirecting after submit button

Hi I have something similar to http://stackoverflow.com/questions/12172571/redirecting-with-k-mvc

@ko.Html.Button("Commit Order", "CommitOrder", "Cart", null, new { @class = "btn btn-default" })

The debugger gets in the commitorder method in the cartcontroller, but when i return json("redirecturl") it does not work. not returing json and redirecting does not work either,

the thing is that i have a case in my code behind where i calculate to what route i need to redirect. Please let me know if you need to see more code or if my issue is not clear.

IIS fails when model has circular references

Hello,

Found, that IIS fails, when model contains circular references.
It is known issue of Microsoft JavaScript Serializer.

Please change the serializer to Json.Net.

Json.Net is faster and has more predictable behavior and I'm already configured my Model to ignore circular references.

DateTime lost after executeOnServer

I tried to work with Model, containing Data.

The format I received from server with first request: /Date(1354656075282)/"}
While executing it sends with correct format.
But when it returned back from server side: /Date(-62135596800000)/

I cheched with debugger - on server side the field already lost.
So, it could be a problem somewhere in KnockoutUtilities.ConvertData.

Could somebody reproduce this issue?

BTW, please send to NuGet fresh version of the library :)

Custom arbitrary tag

Until more support is available for other elements, please add in a ko.Html.Tag("name") to handle creation of any tag.

template performance

hi,
first of all let me say that your project is one of the best thing i have ever seen, thanks a lot for it

i have a question about template performance
for example in this example here
http://knockoutmvc.com/Collections

if you add child to Annabelle , the Bertie and charles collection get re rendered again, also Annabelle it self and all items get re rendered, is it not bad from performance point of view ?

thanks in advanced.

Checkbox issue

There's a model like that

...
{
  List<int> Items...
}

Then when you rendering checkboxes like that

@using(var items = ko.Foreach(m = m.Items)
{
  @items.Html.Checkbox(m => m % 2 == 0);
}

you'll get output like that

<input type="checkbox" data-bind="checked : ((parseInt() % parseInt(2)) == 0)"/>

it should be

<input type="checkbox" data-bind="checked : ((parseInt($data) % parseInt(2)) == 0)"/>

So, I have to use it like that:

@using(var items = ko.Foreach(m = m.Items)
{
  @items.Html.Checkbox(m => "$data % 2 == 0");
}

It works as expect but it's not grace...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.