Materialize CSS examples are not working in Blazor WASM - c#

I'm trying to use the materialize framework for css with a Blazor application, however, when I copy/paste some of the examples into a layout, component, etc I don't get what Materialize shows on the example. There aren't any CSS/JS loading or console errors that can be identified in dev tools, but it seems like something isn't loading because lots of components aren't working as the examples show.
For example, the tab indicator that apperas under the active tab and hops from tab to tab when you select one.
layout page:
#inherits LayoutComponentBase
<div class="main">
<nav class="nav-extended">
<div class="nav-wrapper">
Logo
<i class="material-icons">menu</i>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li>Sass</li>
<li>Components</li>
<li>JavaScript</li>
</ul>
</div>
<div class="nav-content">
<ul class="tabs tabs-transparent">
<li class="tab">Test 1</li>
<li class="tab"><a class="" href="#test2">Test 2</a></li>
<li class="tab disabled">Disabled Tab</li>
<li class="tab">Test 4</li>
</ul>
</div>
</nav>
<div class="content px-4">
#Body
</div>
</div>
Edit
Looks like the M.AutoInit() isn't firing properly. Can someone point out where the best place to call that function would be? I tried a
document.onload = M.AutoInit();
on the index.html page and a interop JS on my component
#code {
...
protected override void OnInitialized()
{
JSRuntime.Invoke<string>("M.AutoInit");
}
...
}
Neither worked but maybe I'm doing the JSInterop wrong, couldn't find a definitive example, similar to what I'm trying to do, in the docs. Any suggestions or pointers would be great!

This works for me(very important respect the async await, so if you have any errors the Exception is properlly thowed to your browser console)
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("M.AutoInit");
}
}

In the static JavaScript file that is used to initialize materialize elements, add AutoInit method to load first on DOMContentLoaded event listener.
Consider this example that initializes Materialize Sidenav:
In the Sidenav.razor:
<nav> <!-- navbar content here -optional --> </nav>
<ul id="slide-out" class="sidenav">
<li>
<div class="user-view">
<div class="background">
<img width="300" src="office.jpg">
</div>
<a href="#user">
<img class="circle" width="50"
src="user_female.svg.png">
</a>
<span class="white-text name">John Doe</span>
<span class="white-text email">xyz#xyz.com</span>
</div>
</li>
<li><i class="material-icons">cloud</i>First Link With Icon</li>
<li>Second Link</li>
<li><div class="divider"></div></li>
<li><a class="subheader">Sub-header</a></li>
<li><a class="waves-effect" href="#!">Third Link With Waves</a></li>
</ul>
<i class="material-icons">menu</i>
In the main.js:
(function () {
"use strict";
var M = window.M || globalThis.M;
function activateSideNav() {
var elems = document.querySelectorAll('.sidenav');
var options = {};
M.Sidenav.init(elems, options);
}
document.addEventListener('DOMContentLoaded', function () {
M.AutoInit();
setTimeout(activateSideNav, 864);
});
})();
In the MainLayout.razor:
<Sidenav />
<div class="row">
<div class="col s12 m12 l12 xl12">
#Body
</div>
</div>
Also make sure that Materialize libraries are referenced properly in the _Host.cshtml
#page "/"
#namespace Example.Pages
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Example</title>
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<base href="~/" />
<link href="css/materialize/css/materialize.css" rel="stylesheet" />
<link href="css/main.css" rel="stylesheet" />
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
<script src="_framework/blazor.server.js"></script>
<script src="css/materialize/js/materialize.js"></script>
<script src="js/main.js"></script>
</body>
</html>

Related

Blazor Loading issue with images and Html Head Component

I got strange flickering when coming to my blazor server side application.
For better user experience I implemented a GIF throbber but afterwards the loading is not fluently as you can see yourself:
https://shop6.gastroblitz.de/streetchooser
My goal is that the page should appear completely and in one refresh after the loading throbber is done:
some ideas for performance issues (but don't have an idea to improve with my current knowledge...):
_Host.cshtml
PreRender "HtmlHeadComponent" in the area (for generating domain specific title, meta data, etc.)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<base href="~/" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="height=device-height,
width=device-width, initial-scale=1.0,
minimum-scale=1.0, maximum-scale=1.0,
user-scalable=no" />
<link rel="stylesheet" href="/css/main.css" />
<link rel="stylesheet" href="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/assets/owl.carousel.min.css" />
<link rel="stylesheet" href="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/assets/owl.theme.default.min.css" />
<script src="_content/Microsoft.AspNetCore.ProtectedBrowserStorage/protectedBrowserStorage.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="/js/animations.js"></script>
<script src="/js/simplebar.min.js"></script>
<script src="/js/articlePopup.js"></script>
<script src="/js/accordion.min.js"></script>
<script src="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/owl.carousel.js"> </script>
<script src="/js/my.js"></script>
<script src="_content/Blazor-Analytics/blazor-analytics.js"></script>
#(await Html.RenderComponentAsync<HtmlHeadComponent>(RenderMode.ServerPrerendered))
</head>
<body>
<app>
#(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="_framework/blazor.server.js"></script>
<script>
Blazor.defaultReconnectionHandler._reconnectCallback = function (d) {
document.location.reload();
}
</script>
<script src="https://cdn.syncfusion.com/ej2/17.4.43/dist/ej2.min.js"></script>
<script src="https://cdn.syncfusion.com/ej2/17.4.43/dist/ejs.interop.min.js"></script>
</body>
</html>
App.razor
Here I just start when every data is loaded (see the if statement + many CascadingParameters for handling data changes in sub components)
<Router AppAssembly="#typeof(Program).Assembly">
<Found Context="routeData">
#if (AppState.StoreData != null &&
AppState.MultiStoreData != null &&
AppState.StoreChooserData != null)
{
<CascadingValue Value="AppState.StoreData" Name="StoreData">
<CascadingValue Value="AppState.MultiStoreData" Name="MultiStoreData">
<CascadingValue Value="AppState.StoreChooserData" Name="StoreChooserData">
<CascadingValue Value="AppState.BasketData" Name="BasketData">
<CascadingValue Value="AppState.CheckoutData" Name="CheckoutData">
<RouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)" />
<GoogleAnalytics TrackingId="#AppState.StoreData?.StoreContainer?.Store?.GoogleAnalyticsId" />
</CascadingValue>
</CascadingValue>
</CascadingValue>
</CascadingValue>
</CascadingValue>
}
else
{
<img class="center" src="/img-dev/ajax-loader.gif" />
}
</Found>
<NotFound>
<LayoutView Layout="#typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
Last step is the given storechooser page which loads content also just when all data is available
#page "/streetchooser"
#inherits StreetChooserBase
#if (StoreChooserData != null && MultiStoreData != null)
{
<div class="slider" id="home">
<div id="owl-demo" class="owl-carousel owl-theme pitch_img">
#if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage1))
{
<div class="item">
<img src="img/#StoreData?.StoreContainer?.Store?.Key/#MultiStoreData.MultiStore.StreetChooserImage1" alt="" class="pitch_img" />
</div>
}
#if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage2))
{
<div class="item">
<img src="img/#StoreData?.StoreContainer?.Store?.Key/#MultiStoreData.MultiStore.StreetChooserImage2" alt="" class="pitch_img" />
</div>
}
#if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage3))
{
<div class="item">
<img src="img/#StoreData?.StoreContainer?.Store?.Key/#MultiStoreData.MultiStore.StreetChooserImage3" alt="" class="pitch_img" />
</div>
}
#if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage4))
{
<div class="item">
<img src="img/#StoreData?.StoreContainer?.Store?.Key/#MultiStoreData.MultiStore.StreetChooserImage4" alt="" class="pitch_img" />
</div>
}
#if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage5))
{
<div class="item">
<img src="img/#StoreData?.StoreContainer?.Store?.Key/#MultiStoreData.MultiStore.StreetChooserImage5" alt="" class="pitch_img" />
</div>
}
</div>
<div class="slider_content ">
<div class="container">
<div class="row ">
<div class="col-sm-5">
#if (StoreChooserData != null && MultiStoreData != null)
{
<EditForm Model="#StoreChooserData">
<div class="search-section">
<div class="search-logo">
<img src="img/#StoreData?.StoreContainer?.Store?.Key/#StoreData?.StoreContainer?.Store?.LogoUrl" alt="" />
</div>
<p>Sushi und mehr online bestellen und abholen oder direkt nach Hause liefern lassen.</p>
<div class="row">
<div class="col-sm-6">
<div class="select-location #(StoreChooserData.OrderType == "1" ? "active" : "")"
#onclick="OrderTypeChangedToDelivery"> Lieferung</div>
</div>
<div class="col-sm-6">
<div class="select-location #(StoreChooserData.OrderType == "2" ? "active" : "")"
#onclick="OrderTypeChangedToPickup"> Selbstabholer</div>
</div>
</div>
<div class="search-rest">
<label>Plz / Ort </label>
<EjsComboBox Value="#StoreChooserData.PostcodeCitySite"
ModelType="#typeof(Db_DeliveryStreet)"
Placeholder="Ort eingeben"
ShowClearButton="true"
AllowCustom="true"
AllowFiltering="true"
FilterType="FilterType.Contains"
NoRecordsTemplate="<div>Keine Ergebnisse</div>"
DataSource="#MultiStoreData.DeliveryZones">
<AutoCompleteEvents TValue="string" ValueChange="PostcodeCityChanged"></AutoCompleteEvents>
<ComboBoxFieldSettings GroupBy="Postcode" Value="FullName"></ComboBoxFieldSettings>
<ComboBoxTemplates>
<GroupTemplate Context="Item">
<span class="group">#((Item as Db_DeliveryStreet).Postcode)</span>
</GroupTemplate>
<ItemTemplate Context="Item">
<span><span class='name'>#((Item as Db_DeliveryStreet).CitySite)</span><span class='minOrderValue'>#($"ab {(Item as Db_DeliveryStreet).MinOrderValue?.ToString("f2")}€")</span></span>
</ItemTemplate>
</ComboBoxTemplates>
</EjsComboBox>
<ValidationMessage For="#(() => StoreChooserData.PostcodeCitySite)">
</ValidationMessage>
</div>
<div class="search-rest">
<label>Straße / Hausnr. </label>
<EjsComboBox Value="#StoreChooserData.Street"
ModelType="#typeof(StreetItem)"
Placeholder="Straße eingeben"
ShowClearButton="true"
AllowCustom="true"
AllowFiltering="true"
FilterType="FilterType.Contains"
NoRecordsTemplate="<div>Keine Ergebnisse</div>"
DataSource="#Streets">
<AutoCompleteEvents TValue="string" ValueChange="StreetChanged"></AutoCompleteEvents>
<ComboBoxFieldSettings Value="Name"></ComboBoxFieldSettings>
</EjsComboBox>
<ValidationMessage For="#(() => StoreChooserData.Street)"></ValidationMessage>
</div>
<div class="search-rest">
<button class="search-send-btn" #onclick="#GoToNext">weiter </button>
</div>
</div>
</EditForm>
}
</div>
</div>
</div>
</div>
</div>
<FooterComponent />
}
Think one issue is that the images are requested very late in my code and produce the flickering...
But how could handle this in a better way? Or maybe another point could be some issue.
Hope you got my point.
Thanks in advance!
I am using MemoryCache to prevent flickering caused by using RenderMode.ServerPrerendered. The issue is discussed in this thread.
The problem with filckering can be avoided by caching the resultset between prerendering and rendering phase on server. Hopefully they fix it somehow in the next release.
On server-side blazor it is simpler and better to use the in memory
cache for that.
It avoids rountripping the state.
It can be combined with a react/redux approach where you simply pass an id for the store and put the store in a memory cache with the
id, which is then used to retrieve the store when the app reconnects
and to produce an identical render to the one it was prerendered.
As an example below is a modified WeatherService that shows that it
causes no flickering.
public WeatherForecastService(IMemoryCache memoryCache)
{
MemoryCache = memoryCache;
}
public IMemoryCache MemoryCache { get; }
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30) });
var rng = new Random();
await Task.Delay(TimeSpan.FromSeconds(10));
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray();
});
}
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
The line await Task.Delay(TimeSpan.FromSeconds(10)); is there just for demonstration purposes, it is certainly not necessary to wait 10 seconds.

C# HTMLAgilityPack Need help creating xpath

<html lang="en" class="gr__r6db_com">
<head>
<meta charset="UTF-8">
<title>Search results for kinglio | R6DB</title>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#ff0000">
<meta id="meta_desc" name="description" content="Search players named kinglio on R6DB">
<meta name="keywords" content="r6db,gitgudscrub,rainbow 6, rainbow six siege, database">
<meta name="apple-mobile-web-app-title" content="R6DB">
<meta name="application-name" content="R6DB">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/app.css">
</head>
<body data-gr-c-s-loaded="true">
<div id="mount">
<div class="app is-results">
<div class="app-background">
<img src="/assets/nippon.jpg" class="clear">
<img src="/assets/nippon-blurred.jpg" class="blur">
</div>
<div class="app-page">
<div class="search">
<h1 class="title is-1 search-title">R6DB</h1>
<div class="search-form">
<div class="column is-small-8 search-input">
<input type="text"><span><input type="checkbox" id="exactSearch"><label for="exactSearch">exact name</label></span>
</div>
<button class="search-submit">Search</button>
</div>
<div class="colums is-multiline search-results">
<div class="playercard player-6881796a-9f51-4386-83f9-136ea45d0faa is-user is-visible">
<a href="/player/6881796a-9f51-4386-83f9-136ea45d0faa" class="card-image">
<img src="/assets/noavatar.png">
</a>
<div class="card-content">
<div class="player-identification">Kinglio<span class="player-id">6881796a-9f51-4386-83f9-136ea45d0faa</span>
</div>
<div class="player-aliases">
<header>known aliases</header>
<ul>
<li>Kinglio</li>
</ul>
</div>› view on uplay
</div>
</div>
<div class="playercard player-344b8c89-7deb-4e0f-ad42-942ee314c072 is-user is-visible">
<a href="/player/344b8c89-7deb-4e0f-ad42-942ee314c072" class="card-image">
<img src="//uplay-avatars.s3.amazonaws.com/344b8c89-7deb-4e0f-ad42-942ee314c072/default_146_146.png">
</a>
<div class="card-content">
<div class="player-identification">KingLio.-<span class="player-id">344b8c89-7deb-4e0f-ad42-942ee314c072</span>
</div>
<div class="player-aliases">
<header>known aliases</header>
<ul>
<li>KingLio.-</li>
<li>KingLio.TG</li>
<li>and 7more</li>
</ul>
</div>› view on uplay
</div>
</div>
<div class="playercard player-922eec9c-61b6-4a09-892e-96ae2be3218d is-user is-visible">
<a href="/player/922eec9c-61b6-4a09-892e-96ae2be3218d" class="card-image">
<img src="//uplay-avatars.s3.amazonaws.com/922eec9c-61b6-4a09-892e-96ae2be3218d/default_146_146.png">
</a>
<div class="card-content">
<div class="player-identification">PS4Gamer.--<span class="player-id">922eec9c-61b6-4a09-892e-96ae2be3218d</span>
</div>
<div class="player-aliases">
<header>known aliases</header>
<ul>
<li>PS4Gamer.--</li>
<li>KingLio.1L</li>
<li>and 2more</li>
</ul>
</div>› view on uplay
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script async="" src="https://www.google-analytics.com/analytics.js"></script>
<script src="/js/app.js"></script>
<iframe src="chrome-extension://hgimnogjllphhhkhlmebbmlgjoejdpjl/bar.html" id="xh-bar" class="hidden"></iframe>
<img id="hzDownscaled" style="position: absolute; top: -10000px;">
</body>
</html>
I am trying to scrape a unique ID from a website depending on what a user enters into a text box. However, I am failing to use a correct Xpath, no matter what I try.
Here is my most recent attempt
string searchUsernameUrl = "https://www.r6db.com/search/" + txtUsername.Text;
HtmlWeb searchWeb = new HtmlWeb();
HtmlAgilityPack.HtmlDocument searchDoc = searchWeb.Load(searchUsernameUrl);
try
{
txtUplayID.Text = searchDoc.DocumentNode.SelectNodes("//div[#class='colums is-multiline search-results']/div[1]/div/div[1]/span")[0].InnerText;
}
catch (NullReferenceException)
{
MessageBox.Show("Unable to find username ID.", "Error");
}
Here is the html code to the website. Upon searching, any number of results may appear. In this example there are 3. I only want to copy the code from the first example.
Here is a picture of the HTML from the website upon searching, showing what I need an xpath for

Unable to open the cshtml page

I have developed an application and deployed to cloud. By default index page is loading but once index page is loaded on click on it it will open other page(cshtml page). But i am getting blank page . Please help
Index.cshtml code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Create Invoice Online for Free & Download PDF</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="../Content/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="../Content/bootstrap-responsive.min.css" />
<link rel="stylesheet" type="text/css" href="../Content/quick-invoice.css" />
<script type="text/javascript" src="../Content/jquery.js"></script>
<script type="text/javascript" src="../Content/bootstrap.min.js"></script>
<meta name="google-site-verification" content="FB0t_l2pYlfmLe1hzPyjLXXhDF8Bufut_nDhCP5brrQ" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="/">Invoices generator</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active"><i class="icon-home icon-white"></i>Home</li>
<li><i class="icon-file icon-white"></i> Invoice Templates</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container layout">
<div class="row">
<div class="span9">
<div class="container-narrow">
<div class="container-narrow jumbotron">
<h1>Shopping Cart Online Invoice Generator</h1>
<p class="lead">Create & Send your invoice without having to register, and download as <strong>PDF, </strong>quickly & easily for free, email your invoice Select an invoice template from our invoices templates list, Save or send your invoice in minutes</p>
<hr /> Create your invoice
<hr />
</div>
</div>
<div class="pop-layouts">
<h4>Invoice Templates</h4>
<ul class="thumbnails">
<li>
<h4>Shopping Cart Invoice Template</h4>
<a class="thumbnail" href="create" title="Shopping Cart Invoice Template">
<img src="../Images/057e7_b4a13_1.jpg" alt="" date-large="../Images/4dad1_733d6_1.png" />
</a>
<div class="caption">
<!--<i class="icon-eye-open icon-white"></i> Preview-->
<i class="icon-plus-sign icon-white"></i> Create
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<script type="text/javascript">
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date(); a = s.createElement(o),
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
ga('shopping-cart-invoices', 'UA-47492117-1', 'mybluemix.net');
ga('send', 'pageview');
</script>
</body>
</html>
Startup.cs
using System;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
using Microsoft.AspNet.StaticFiles;
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseServices(services =>
{
services.AddMvc();
});
app.UseFileServer(new FileServerOptions()
{
EnableDirectoryBrowsing = false,
});
app.Use(async (context, next) =>
{
Console.WriteLine(context.Request.Path);
try
{
await next();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "Default",
template: "{controller=Home}/{action=Index}/{id?}"
);
routes.MapRoute(
name: "CreateInvoice",
template: "{controller=CreateInvoice}/{action=Create}/{id?}"
);
routes.MapRoute(
name: "Preview",
template: "{controller=Preview}/{action=preview}/{id?}"
);
routes.MapRoute(
name: "Thanks",
template: "{controller=Thanks}/{action=Thankyou}/{id?}");
});
}
}
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
You should be using
#Html.actionlink("Create", "CreateInvoice")
This will allow you to declare the action and the controller
It also means that you will get build errors if the action or controller do not exist

button not disabling after click

I am using this post to disable my buttons on click:
Prevent multiple form submits in MVC 3 with validation
This is my page source after it is rendered:
<!DOCTYPE html>
<html>
<head>
<title>Do not bookmark this page.</title>
<link href="/Content/reset.css" rel="stylesheet" type="text/css" />
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="/Content/styer.css?t=335" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="/Scripts/Views/main.js" type="text/javascript"></script>
<link rel="shortcut icon" href="/Content/favicon.ico" type="image/ico" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<script language="javascript" type="text/javascript">
$(function () {
$('form').submit(function () {
if ($(this).valid()) {
$('input[type="submit"]').attr('disabled', 'disabled');
}
});
});
</script>
</head>
<body>
<div class="page">
<div id="header">
<div id="headerimg"></div>
<div id="logindisplay">
[ Log On ]
</div>
<div id="menucontainer">
<ul id="menu">
<li>Home</li>
<li>Logon</li>
<li>Register</li>
<li>Contact Us</li>
<li>News</li>
</ul>
</div>
<div id="main">
<h2>Forgot Username</h2>
<p>
Please provide the email address on your web account. Once validated, your username will be sent to your email address for your records.
</p>
<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
<form action="/Account/ForgotUsername" method="post"> <div>
<fieldset>
<legend>Email address</legend>
<div class="editor-label">
<label for="EmailAddress">Email</label>
</div>
<div class="editor-field focus">
<input class="GenericTextBox" data-val="true" data-val-length="The Email must be at least 7 characters long." data-val-length-max="100" data-val-length-min="7" id="EmailAddress" name="EmailAddress" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="EmailAddress" data-valmsg-replace="true"></span>
</div>
<p>
<input id="btn" class="makePaymentInput" type="submit" value="Submit"/>
</p>
</fieldset>
</div>
</form>
<div style="clear: both;"></div>
</div>
<div id="footer">
</div>
</div>
</div>
<!-- Start of StatCounter Code for Default Guide -->
<script type="text/javascript">
var sc_project = 9150358;
var sc_invisible = 1;
var sc_security = "1af31df9";
var scJsHost = (("https:" == document.location.protocol) ? "https://secure." : "http://www.");
document.write("<sc" + "ript type='text/javascript' src='" + scJsHost + "statcounter.com/counter/counter.js'></" + "script>");
</script>
<noscript>
<div class="statcounter"><a title="web analytics" href="http://statcounter.com/" target="_blank"><img class="statcounter" src="http://c.statcounter.com/9150358/0/1af31df9/1/" alt="web analytics"></a></div>
</noscript>
<!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
{"appName":"Internet Explorer"}
</script>
<script type="text/javascript" src="http://localhost:25759/610299fe88d74cee8d0267b4fc859da0/browserLink" async="async"></script>
<!-- End Browser Link -->
</body>
</html>
This works on most forms but this one, which is the main reason I used this code.
Anyone see why this one is not working?
Instead of writing this :-
$('input[type="submit"]').attr('disabled', 'disabled');
You should write this :-
$('input[type="submit"]').prop('disabled','true');

Creating a KnockoutJS Model From an ASP.NET MVC complex model

I would like to create knockout viewModel from asp.net MVC model using ko.mapping.fromJS() method but my form didn't populating values.
In view I created script looks like that:
<script type="text/javascript">
var tmp = #Html.Raw(Model.ToJson());
var viewModel = ko.mapping.fromJS(tmp);
ko.applyBindings(viewModel);
</script>
#Html.Raw(Model.ToJson() returns value
{"id":1,
"surveyCode":null,
"title":"Życie",
"description":"Ankieta, w której zadawane będą pytania na temat codziennego życia ",
"dateStart":"2013-12-12T00:00:00",
"dateEnd":"2014-12-30T00:00:00",
"createDate":"2014-01-07T03:23:16.053",
"lastModification":"2014-01-07T03:23:16.053",
"isActive":false,
"questions":[{"id":1,
"surveyID":1,
"content":"Co jesz na śniadanie?",
"tips":"wybierz jedną odpowiedź",
"questionType":1,
"isRequired":true,
"answers": [{"id":1,
"questionID":1,
"answerContent":"Jajecznicę",
"isOpenAnswer":false},
{"id":2,
"questionID":1,
"answerContent":"Kiełbaski",
"isOpenAnswer":false},
{"id":3,
"questionID":1,
"answerContent":"Płatki na mleku",
"isOpenAnswer":false},
{"id":4,
"questionID":1,
"answerContent":"Inne",
"isOpenAnswer":true}]},
{"id":2,
"surveyID":1,
"content":"Czym się zajmujesz w życiu?",
"tips":"napisz krótką historię",
"questionType":3,
"isRequired":true,
"answers":[]}]}
but when I want to bind 'title' property to <span> <span data-bind="text:title"></span> it is not working. When I run my app in firefox and turn on firebug script console and set breakpiont to line var tmp = #Html.Raw(Model.ToJson()); returns correct value, press F10 going to next line var viewModel = ko.mapping.fromJS(tmp); and finally press F10 and nothing happen, script not execute next line ko.applyBindings(viewModel);.
And it is my question. Is it possible to mapp my mvc model using knockout mapping plugin automacly? or maybe should I do some manualy staf to map mvc model to knockout viewModel.
I'm looking for answers on this sites:
link1
and
stackowerflow
but maybe I didn't understand this posts.
Edit
my view looks like this:
#using Inżynierka.Extensions
#model Inżynierka.Models.Survey
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>SurveyAnswer</h4>
<hr />
#Html.ValidationSummary(true)
Title: <span data-bind="text:title"></span>
</div>
}
#section Scripts {
<script src="../../Scripts/jQuery.tmpl.min.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-3.0.0.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.validation.js"></script>
<script src="../../Scripts/knockout.knockout.mapping-latest.js"></script>
<script type="text/javascript">
var tmp = #Html.Raw(Model.ToJson());
var viewModel = ko.mapping.fromJS(tmp);
ko.applyBindings(viewModel);
</script>
#Scripts.Render("~/bundles/jqueryval")
}
Edit 2
It is html sourse of my page:
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js'></script>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Create</title>
<link href="/Content/bootstrap.css" rel="stylesheet"/>
<link href="/Content/site.css" rel="stylesheet"/>
<script src="/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Ankietyy</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>Moje Ankiety</li>
<li>Strona Główna</li>
<li>O Projekcie</li>
<li>Kontakt</li>
</ul>
<form action="/Account/LogOff" class="navbar-right" id="logoutForm" method="post"><input name="__RequestVerificationToken" type="hidden" value="fWDZFmyGqJyU3ATUf2IbHDdkbo22bzObUMwUfxfqwXIiqGvRYzMhApWS3I5GkkHnZD7ieDxLfh84s2-prLDtSGeE6_D7p7cT-fmQBszeM06p-fZ7RzhOPn0P8EDftLRwT8YQA8t2U56dlLX_lx3G4Q2" /> <ul class="nav navbar-nav navbar-right">
<li>
Witaj Bartek!
</li>
<li>Wyloguj się</li>
</ul>
</form>
</div>
</div>
</div>
<div class="container body-content">
<form action="/SurveyAnswer/CompleteSurvey/1" method="post"><input name="__RequestVerificationToken" type="hidden" value="KOALGZbw0WhFlBV4LHx530Oen59aBWF62b6s58GIUikx3A62uhcAi3-74auJpLtI4fYj9kmcPjlgNu1TeuNrYukpFlll1cGCOIcjjewtFou4M9C3_bHDFk7UoZk_tKpw7SxcXa3UbgwIj4ZhCRM6_g2" /> <div class="form-horizontal">
<h4>SurveyAnswer</h4>
<hr />
Title: <span data-bind="text:title"></span>
</div>
</form><script type="text/javascript">
var tmp = {"id":1,"surveyCode":null,"title":"Życie","description":"Ankieta, w której zadawane będą pytania na temat codziennego życia ","dateStart":"2013-12-12T00:00:00","dateEnd":"2014-12-30T00:00:00","createDate":"2014-01-07T03:23:16.053","lastModification":"2014-01-07T03:23:16.053","isActive":false,"questions":[{"id":1,"surveyID":1,"content":"Co jesz na śniadanie?","tips":"wybierz jedną odpowiedź","questionType":1,"isRequired":true,"answers":[{"id":1,"questionID":1,"answerContent":"Jajecznicę","isOpenAnswer":false},{"id":2,"questionID":1,"answerContent":"Kiełbaski","isOpenAnswer":false},{"id":3,"questionID":1,"answerContent":"Płatki na mleku","isOpenAnswer":false},{"id":4,"questionID":1,"answerContent":"Inne","isOpenAnswer":true}]},{"id":2,"surveyID":1,"content":"Czym się zajmujesz w życiu?","tips":"napisz krótką historię","questionType":3,"isRequired":true,"answers":[]},{"id":14,"surveyID":1,"content":"Pytanie końcowe","tips":"napisz","questionType":1,"isRequired":true,"answers":[{"id":9,"questionID":14,"answerContent":"test","isOpenAnswer":false},{"id":10,"questionID":14,"answerContent":"test2","isOpenAnswer":false},{"id":11,"questionID":14,"answerContent":"test3","isOpenAnswer":false}]}],"surveyAnswers":[],"codeForUsers":[]};
var viewModel = ko.mapping.fromJS(tmp);
ko.applyBindings(viewModel);
</script>
<hr />
<footer>
<p>© 2014 - My ASP.NET Application</p>
</footer>
</div>
<script src="/Scripts/jquery-2.0.3.js"></script>
<script src="/Scripts/bootstrap.js"></script>
<script src="/Scripts/respond.js"></script>
<script src="../../Scripts/jQuery.tmpl.min.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-3.0.0.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.validation.js"></script>
<script src="../../Scripts/knockout.mapping-latest.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
<!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
{"appName":"Firefox","requestId":"9f8e517696004299808eb3caccb0e136"}
</script>
<script type="text/javascript" src="http://localhost:11897/dc47e85290da49019e6425ddd16f962a/browserLink" async="async"></script>
<!-- End Browser Link -->
</body>
</html>
Answer for my issue
View should looks like that:
#using Inżynierka.Extensions
#model Inżynierka.Models.Survey
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>SurveyAnswer</h4>
<hr />
#Html.ValidationSummary(true)
Title: <span data-bind="text:title"></span>
</div>
}
#section Scripts {
<script src="../../Scripts/knockout-3.0.0.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.mapping-latest.js"></script>
<script type="text/javascript">
var tmp = #Html.Raw(Model.ToJson());
var viewModel = ko.mapping.fromJS(tmp);
ko.applyBindings(viewModel);
</script>
#Scripts.Render("~/bundles/jqueryval")
}
Thanks everyone for replies, specially for #VolodymyrBilyachat whose advices were most relevant.
Well after you post source, then other idea what it could is that some scripts are conflicting, try to remove scripts and left only knockout ones
Wrap your knockout view model in a document.ready function
<script type="text/javascript">
$document.ready(function() {
var tmp = #Html.Raw(Model.ToJson());
var viewModel = ko.mapping.fromJS(tmp);
ko.applyBindings(viewModel);});
</script>
Also note that your viewModel isn't a true view model at that point so consider using a view model that contains the ko.observable property 'myData' or something to hold your data and then applying bindings
For complex models I don't believe mappings and simply, I'm parsing json on my own and populate model via loops, ifs and so on. I think, this isn't the worst solution, because debugging and fixing data becomes simplier.

Categories

Resources