diff --git a/src/Framework/Framework/Compilation/Javascript/JavascriptTranslatableMethodCollection.cs b/src/Framework/Framework/Compilation/Javascript/JavascriptTranslatableMethodCollection.cs index 9c56f3ac5a..5aa3f7826c 100644 --- a/src/Framework/Framework/Compilation/Javascript/JavascriptTranslatableMethodCollection.cs +++ b/src/Framework/Framework/Compilation/Javascript/JavascriptTranslatableMethodCollection.cs @@ -782,9 +782,13 @@ JsExpression wrapInRound(JsExpression a) => private void AddDataSetOptionsTranslations() { // GridViewDataSetBindingProvider - AddMethodTranslator(typeof(GridViewDataSetBindingProvider), "DataSetClientSideLoad", new GenericMethodCompiler(args => + AddMethodTranslator(() => GridViewDataSetBindingProvider.DataSetClientSideLoad(null!), new GenericMethodCompiler(args => new JsIdentifierExpression("dotvvm").Member("dataSet").Member("loadDataSet").Invoke(args[1].WithAnnotation(ShouldBeObservableAnnotation.Instance), new JsSymbolicParameter(JavascriptTranslator.KnockoutContextParameter).Member("$gridViewDataSetHelper").Member("loadDataSet")).WithAnnotation(new ResultIsPromiseAnnotation(e => e)))); + AddMethodTranslator(() => GridViewDataSetBindingProvider.GetCurrentGridDataSet(), new GenericMethodCompiler(args => + new JsSymbolicParameter(JavascriptTranslator.KnockoutContextParameter).Member("$gridViewDataSetHelper").Member("dataSet") + )); + // PagingOptions AddMethodTranslator(() => default(PagingOptions)!.GoToFirstPage(),new GenericMethodCompiler(args => new JsIdentifierExpression("dotvvm").Member("dataSet").Member("translations").Member("PagingOptions").Member("goToFirstPage") diff --git a/src/Framework/Framework/Compilation/Javascript/MemberInfoHelper.cs b/src/Framework/Framework/Compilation/Javascript/MemberInfoHelper.cs index 248241f59c..3e658b317c 100644 --- a/src/Framework/Framework/Compilation/Javascript/MemberInfoHelper.cs +++ b/src/Framework/Framework/Compilation/Javascript/MemberInfoHelper.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; +using DotVVM.Framework.Controls; namespace DotVVM.Framework.Compilation.Javascript { @@ -154,6 +155,7 @@ public static class Generic { public record T { } public enum Enum { Something } public record struct Struct { } + public class DataSet: GridViewDataSet { } } } } diff --git a/src/Framework/Framework/Controls/DataPager.cs b/src/Framework/Framework/Controls/DataPager.cs index 2414cbb4aa..ade19dd426 100644 --- a/src/Framework/Framework/Controls/DataPager.cs +++ b/src/Framework/Framework/Controls/DataPager.cs @@ -189,10 +189,12 @@ protected virtual void DataBind(Hosting.IDotvvmRequestContext context) if (DataSet is IPageableGridViewDataSet dataSet) { + var currentPageTextContext = DataContextStack.Create(typeof(int), dataContextType); var i = 0; foreach (var number in dataSet.PagingOptions.NearPageIndexes) { var li = new HtmlGenericControl("li"); + li.SetDataContextType(currentPageTextContext); li.SetBinding(DataContextProperty, GetNearIndexesBinding(context, i, dataContextType)); if (number == dataSet.PagingOptions.PageIndex) { @@ -283,7 +285,7 @@ protected override void AddAttributesToRender(IHtmlWriter writer, IDotvvmRequest var loadDataExpression = KnockoutHelper.GenerateClientPostbackLambda("LoadData", loadData, this, new PostbackScriptOptions(elementAccessor: "$element", koContext: CodeParameterAssignment.FromIdentifier("$context"))); helperBinding.Add("loadData", loadDataExpression); } - writer.AddKnockoutDataBind("dotvvm-gridviewdataset", helperBinding); + writer.AddKnockoutDataBind("dotvvm-gridviewdataset", helperBinding.ToString()); // If Visible property was set to something, it will be overwritten by this. TODO: is it how it should behave? if (HideWhenOnlyOnePage) @@ -293,7 +295,7 @@ protected override void AddAttributesToRender(IHtmlWriter writer, IDotvvmRequest writer.AddKnockoutDataBind("visible", $"({dataSetBinding}).PagingOptions().PagesCount() > 1"); } - writer.AddKnockoutDataBind("with", this, DataSetProperty, renderEvenInServerRenderingMode: true); + // writer.AddKnockoutDataBind("with", this, DataSetProperty, renderEvenInServerRenderingMode: true); if (GetValueBinding(EnabledProperty) is IValueBinding enabledBinding) @@ -345,11 +347,11 @@ protected override void RenderContents(IHtmlWriter writer, IDotvvmRequestContext writer.WriteKnockoutDataBindEndComment(); AddItemCssClass(writer, context); - AddKnockoutDisabledCssDataBind(writer, context, "PagingOptions().IsLastPage()"); + AddKnockoutDisabledCssDataBind(writer, context, "$gridViewDataSetHelper.dataSet.PagingOptions().IsLastPage()"); GoToNextPageButton!.Render(writer, context); AddItemCssClass(writer, context); - AddKnockoutDisabledCssDataBind(writer, context, "PagingOptions().IsLastPage()"); + AddKnockoutDisabledCssDataBind(writer, context, "$gridViewDataSetHelper.dataSet.PagingOptions().IsLastPage()"); GoToLastPageButton!.Render(writer, context); } @@ -366,7 +368,7 @@ protected virtual void RenderPageNumberButton(IHtmlWriter writer, IDotvvmRequest if (!RenderLinkForCurrentPage) { - writer.AddKnockoutDataBind("visible", "$data == $parent.PagingOptions().PageIndex()"); + writer.AddKnockoutDataBind("visible", "$data == $parentContext.$gridViewDataSetHelper.dataSet.PagingOptions().PageIndex()"); AddItemCssClass(writer, context); writer.AddAttribute("class", ActiveItemCssClass, true); var literal = new Literal(); @@ -377,7 +379,7 @@ protected virtual void RenderPageNumberButton(IHtmlWriter writer, IDotvvmRequest li.Render(writer, context); - writer.AddKnockoutDataBind("visible", "$data != $parent.PagingOptions().PageIndex()"); + writer.AddKnockoutDataBind("visible", "$data != $parentContext.$gridViewDataSetHelper.dataSet.PagingOptions().PageIndex()"); } li = new HtmlGenericControl("li"); @@ -388,9 +390,9 @@ protected virtual void RenderPageNumberButton(IHtmlWriter writer, IDotvvmRequest AddItemCssClass(writer, context); if (RenderLinkForCurrentPage) - AddKnockoutActiveCssDataBind(writer, context, "$data == $parent.PagingOptions().PageIndex()"); + AddKnockoutActiveCssDataBind(writer, context, "$data == $parentContext.$gridViewDataSetHelper.dataSet.PagingOptions().PageIndex()"); - li.SetValue(Internal.PathFragmentProperty, "PagingOptions.NearPageIndexes[$index]"); + li.SetValue(Internal.PathFragmentProperty, "$parent.PagingOptions.NearPageIndexes[$index]"); var link = new LinkButton(); li.Children.Add(link); link.SetDataContextType(currentPageTextContext); @@ -402,6 +404,12 @@ protected virtual void RenderPageNumberButton(IHtmlWriter writer, IDotvvmRequest li.Render(writer, context); } + // protected override void RenderEndTag(IHtmlWriter writer, IDotvvmRequestContext context) + // { + // base.RenderEndTag(writer, context); + // writer.WriteKnockoutDataBindEndComment(); + // } + private IValueBinding GetDataSetBinding() => GetValueBinding(DataSetProperty) ?? throw new DotvvmControlException(this, "The DataSet property of the dot:DataPager control must be set!"); } diff --git a/src/Framework/Framework/Controls/GridViewDataSetBindingProvider.cs b/src/Framework/Framework/Controls/GridViewDataSetBindingProvider.cs index 69a447a2a9..c9af459673 100644 --- a/src/Framework/Framework/Controls/GridViewDataSetBindingProvider.cs +++ b/src/Framework/Framework/Controls/GridViewDataSetBindingProvider.cs @@ -139,6 +139,7 @@ private ICommandBinding CreateCommandBinding(GridViewDataSetC new object[] { new ParsedExpressionBindingProperty(expression), + new OriginalStringBindingProperty($"DataPager: _dataSet.{methodName}({string.Join(", ", arguments.AsEnumerable())})"), // For ID generation dataContextStack }); } @@ -175,6 +176,12 @@ private static Expression CallClientSideLoad(Expression dataSetParam) return Expression.Call(method, dataSetParam); } + private static Expression CurrentGridDataSetExpression(Type datasetType) + { + var method = typeof(GridViewDataSetBindingProvider).GetMethod(nameof(GetCurrentGridDataSet))!.MakeGenericMethod(datasetType); + return Expression.Call(method); + } + /// /// A sentinel method which is translated to load the GridViewDataSet on the client side using the Load delegate. /// Do not call this method on the server. @@ -184,6 +191,12 @@ public static Task DataSetClientSideLoad(IBaseGridViewDataSet dataSet) throw new InvalidOperationException("This method cannot be called on the server!"); } + /// Returns the DataSet we currently work on from the $context.$gridViewDataSetHelper.dataSet + public static T GetCurrentGridDataSet() where T : IBaseGridViewDataSet + { + throw new InvalidOperationException("This method cannot be called on the server!"); + } + private static Type GetOptionsConcreteType(Type dataSetConcreteType, out PropertyInfo optionsProperty) { if (!typeof(TDataSetInterface).IsGenericType || !typeof(TDataSetInterface).IsAssignableFrom(dataSetConcreteType))