rid*_*nsb 1 javascript mvvm asp.net-mvc-4 knockout.js
注册产品时,用户可以自定义它的URL!当用户输入Tipo de produto,Nome或者Link,网站将显示该产品的URL如何

请注意,"Tipo de produto"字段也会修改URL !!
为此,我在KnockoutJS中创建了一个帮助器
KnockoutJS
ko.bindingHandlers.url =
update: (element, valueAccessor, allBindingsAccessor, viewModel) ->
link = ko.utils.unwrapObservable(valueAccessor())
if link
link = link.toLowerCase().trim().replaceAll(" ", "-")
link = encodeURI(link)
else
link = ""
valueAccessor()(link)
$(element).nextAll(".link-exibicao").text(link).effect("highlight", { color: "#FDBB30" }, 800 )
Run Code Online (Sandbox Code Playgroud)
此帮助程序的唯一目的是生成有效的URL并在span中显示它 .link-exibicao
视图模型
public class ProdutoViewModel
{
[AdditionalMetadata("data-bind", "event: { change: function(data) { Link(data.Nome()); }}")]
public string Nome { get; set; }
[DataType(DataType.Url)]
[AdditionalMetadata("Prefixo", "Produto/")]
public string Link { get; set; }
[Display(Name = "Descrição")]
[DataType(DataType.MultilineText)]
public string Descricao { get; set; }
public int? Ordem { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
AdditionalMetadata将添加具有该名称和值的属性.例如,该属性Name将生成HTML:
<input data-bind="value: Nome, event: { change: function(data) { Link(data.Nome()); }}" id="Nome" name="Nome" type="text" value="">
Run Code Online (Sandbox Code Playgroud)
Url.cshtml
下一步是data-bind="url: Link"在URL类型的所有字段中添加标记:
@model string
@{
var values = ViewData.ModelMetadata.AdditionalValues;
object objDatabind;
string data_bind = "";
if (values.TryGetValue("data-bind", out objDatabind))
{
data_bind = objDatabind.ToString();
}
var nomeCampo = Html.IdForModel();
var objPrefixo = values["Prefixo"];
string prefixo = objPrefixo.ToString();
string separador = "/";
if (!string.IsNullOrWhiteSpace(prefixo))
{
if (prefixo.EndsWith("/") || prefixo.EndsWith("#"))
{
separador = prefixo[prefixo.Length - 1].ToString();
prefixo = prefixo.Substring(0, prefixo.Length - 1);
}
}
}
@Html.TextBoxFor(p => Model, new { data_bind = "value: " + nomeCampo + ", url: " + nomeCampo + (string.IsNullOrWhiteSpace(data_bind) ? "" : ", " + data_bind) })
@Request.Url.Host/<span class="link-prefixo">@prefixo</span><span class="link-separador">@separador</span><span class="link-exibicao"></span>
Run Code Online (Sandbox Code Playgroud)
ProdutoViewModel.cshtml
最后,最简单的步骤是构建form =):
<div class="editor-label">
<label>Tipo de produto</label>
</div>
<div class="editor-field">
<select data-bind="options: Tipos, optionsText: 'Nome', value: TipoSelecionado, optionsCaption: 'Selecione...'"></select>
</div>
<div class="editor-label">
@Html.LabelFor(p => p.Nome)
</div>
<div class="editor-field">
@Html.EditorFor(p => p.Nome)
@Html.ValidationMessageFor(p => p.Nome)
</div>
<div class="editor-label">
@Html.LabelFor(p => p.Link)
</div>
<div class="editor-field">
@Html.EditorFor(p => p.Link)
@Html.ValidationMessageFor(p => p.Link)
</div>
<div class="editor-label">
@Html.LabelFor(p => p.Descricao)
</div>
<div class="editor-field">
@Html.EditorFor(p => p.Descricao)
@Html.ValidationMessageFor(p => p.Descricao)
</div>
<div class="editor-label">
@Html.LabelFor(p => p.Ordem)
</div>
<div class="editor-field">
@Html.EditorFor(p => p.Ordem)
@Html.ValidationMessageFor(p => p.Ordem)
</div>
Run Code Online (Sandbox Code Playgroud)
每当键入简单的单词如:"我的产品名称"一切都完美无缺!
但是meu prodúto côm açênto会显示如下错误的字样!
Uncaught Error: Unable to parse bindings.
Message: RangeError: Maximum call stack size exceeded;
Bindings value: value: Link, url: Link
Run Code Online (Sandbox Code Playgroud)
RP *_*yer 11
在访问值时,bindingHandler会导致递归更新:
link = ko.utils.unwrapObservable(valueAccessor())
然后设置它:
valueAccessor()(link)
如果link最终与其当前值相同,则链将停止(可观察者不通知相同的(===)值).
当你通过时: meu prodúto côm açênto
它成为了: meu-prod%C3%BAto%20c%C3%B4m%20a%C3%A7%C3%AAnto
设置observable时,它会重新触发相同的绑定.所以,它encodeURI再次调用,现在它是双重编码,如:
meu-prod%25C3%25BAto%2520c%25C3%25B4m%2520a%25C3%25A7%25C3%25AAnto
observable再次设置,因为这个值是新的,它会再次触发它(并一次又一次),直到你得到调用堆栈错误.
处理这个问题的一些选择是不回写observable并只使用绑定来编码URL.
否则,一个好的选择是使用a writeable computed observable来拦截对值的写入并在模型中对其进行操作.
| 归档时间: |
|
| 查看次数: |
4616 次 |
| 最近记录: |