-->Questions are at the end of the post.
I want to use ExtJs on a multipage application with ASP.NET MVC. I know one of the MVC purposes is to build clean and fast HTML pages, but let's just say I have to use ExtJs.
Given the fact that ExtJs is mainly a single page app oriented framework, I had to find a way to make it work on multipage apps.
So, my layout page looks like this:
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - My ASP.NET MVC Application</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
#*Scripts.Render("~/bundles/modernizr")*#
#Styles.Render("~/Resources/css/app.css")
#Styles.Render("~/ExtJs/ext-theme-neptune-all-debug_01.css")
#Styles.Render("~/ExtJs/ext-theme-neptune-all-debug_02.css")
#Scripts.Render("~/ExtJs/ext-all-debug.js")
#Scripts.Render("~/App/app.js")
#RenderSection("actionscripts", required: false)
</head>
<body>
<div id="body">
<section class="">
#RenderBody()
</section>
</div>
</body>
</html>
App.js is my app starter and simplified looks like this:
APP = {}
BuildActionHTML = null;
Ext.application({
name: 'MyApp',
launch: function () {
APP = this;
APP.VIEWPORT = Ext.create('Ext.container.Viewport', {
layout: 'border',
cls: 'spViewport',
maxWidth: 1280,
minWidth:960,
items: [{
region: 'center',
xtype: 'panel',
title: 'Main content',
items: [{
xtype: 'label',
html: '<div id = "mainAppContainer"></div>',
listeners: {
afterrender: function (label, eOpts) {
BuildActionHTML && typeof BuildActionHTML == 'function' && BuildActionHTML();
}
}
}]
}]
});
}
});
Now, my Index view in Home controller (and any other view) looks like this:
#section actionscripts
{
<script type="text/javascript">
function BuildActionHTML() {
Ext.create('Ext.panel.Panel', {
title: 'My panel',
width: '100%',
renderTo: 'mainAppContainer',
items: [{
xtype: 'textfield',
fieldLabel: 'Text field'
}]
})
}
</script>
}
So my viewport contains a panel with a label which has a label in it. After rendering the label with that <div id = "mainAppContainer"></div> I know for sure I can start rendering my view in it, by calling BuildActionHTML()
1. My question is how bad is this approach, because I know for sure it is not elegant. What "problems" will I probably get into and what are the advantages/disadvantages.
2. Also, how can I customize ext-all.js to use only the classes and components I am using in application, to reduce its size. I don't think I can to this with sencha cmd due to my app architecture (or the lack of it).
Thank you.
Related
I am trying to use tail.select from https://github.com/pytesNET/tail.select.
On the first page load its running well like what I want.
but when I call the row.add method from datatables, each dropdown not working anymore.
Hope somebody can help me to solve this issue.
Best Regards
Thankyou.
In the question's code, I assume that $('#master-row').html() is returning a fragment of HTML - possibly the contents of a <td>.
However, the DataTable row.add() function expects a JavaScript data structure - a JS array or object.
You can provide a variable containing "master row" data using something like this:
var masterRow = [
"",
"<select class=\"select2\"><option>first</option><option>second</option><option>third</option></select>",
"<textarea rows=\"3\" cols=\"20\"></textarea>"
];
It doesn't have to be hard-coded JS like this. It could also be sourced from an ajax call. But for this demo, I will use the above approach.
You can now use this "master row", containing three column values, as follows:
Here is the full HTML page for the demo:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
<!-- tail.select -->
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tail.select#latest/css/tail.select-default.css" />
<script src="https://cdn.jsdelivr.net/npm/tail.select#latest/js/tail.select.min.js"></script>
</head>
<body>
<div style="margin: 20px;">
<button type="button" class="btn-add">New Row!</button>
<br><br>
<table id="example" class="display dataTable cell-border" style="width:100%">
</table>
</div>
<script type="text/javascript">
var masterRow = [
"",
"<select class=\"select2\"><option>first</option><option>second</option><option>third</option></select>",
"<textarea rows=\"3\" cols=\"20\"></textarea>"
];
var dataSet = [];
dataSet.push(masterRow);
$(document).ready(function() {
var table = $('#example').DataTable( {
data: dataSet,
paging: false,
searching: false,
ordering: false,
columnDefs: [
{
targets: 0,
title: "Num",
render: function(data, type, row, meta) {
console.log(data);
return meta.row + 1;
}
},
{
targets: 1,
title: "Select Column"
},
{
targets: 2,
title: "Textarea Column"
}
]
}).on('draw', function() {
tail.select(".select2", {
search: true
});
});
table.draw();
$('.btn-add').click(function() {
table.row.add(masterRow).draw();
});
} );
</script>
</body>
</html>
Notes:
The dataSet variable takes the master row array and adds it into another outer array. This is needed so that we have a full 2-dimensional data structure for DataTables to use when it first loads the table. It is a 2D structure, but with only one (initial) row of data:
When we click on the "new row" button, it uses the masterRow variable as its source for the contents of the new row, resulting in this:
As you can see, the table has a new row, and the drop-downs are working as expected.
You can see the official documentation here for more details about the row.add() API call.
Within sitefinity I am create a widget that I want to initialize KendoGrid and populate the data. For the widget do I need to add the javascript onto the view or is there another way?
The kendo scripts and styles have to be included on the page one way or the other.
You do it either via the view of the widget or (if you use them on many places) you may include them in the main page template.
Some people like to also bundle them into a single local file, as opposed to downloading them from the kendo cdn.
Update:
Controller:
[HttpGet]
public ActionResult Index()
{
// fill the model with data
var model = InitializeModel();
return View("Index", model);
}
Index view
#using Telerik.Sitefinity.Modules.Pages;
#using Telerik.Sitefinity.Frontend.Mvc.Helpers;
#using Newtonsoft.Json;
#using Telerik.Sitefinity.Services;
#using Telerik.Sitefinity.UI.MVC;
#model List<SitefinityWebApp.Mvc.Models.Country>
#if (!SystemManager.IsDesignMode)
{
#Html.Script(ScriptRef.JQuery, "top")
<script src="https://kendo.cdn.telerik.com/2017.3.913/js/kendo.web.min.js"></script>
<link href="https://kendo.cdn.telerik.com/2017.3.913/styles/kendo.common-bootstrap.min.css" rel="stylesheet" />
<link href="https://kendo.cdn.telerik.com/2017.3.913/styles/kendo.bootstrap.min.css" rel="stylesheet" />
<div id="grid"></div>
<script>
var data = #Html.Raw(JsonConvert.SerializeObject(Model));
$(function () {
$("#grid").kendoGrid({
dataSource: {
data: data,
schema: {
model: { id: "Id" }
},
pageSize: 10
},
pageable: true,
scrollable: false,
persistSelection: true,
sortable: true,
columns: [
{ selectable: true, width: "50px" },
{ field: "Title", title: "Country" },
{ field: "CountryCode", title: "Country Code" },
{ field: "CurrencyCode", title: "Currency Code" },
{ field: "Id" }]
});
})
</script>
}
I'm trying to display a simple dgrid as per the first demo on this page:
http://dgrid.io/tutorials/1.0/grids_and_stores/
The only trick is that I'm trying to put it inside an existing structure of containers. So I tried the onFocus event of the container, but when I click on that container, the grid is not showing, and no console.log message appears.
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props='title:"CustomersGrid"'>
<script type='dojo/on' data-dojo-event='onFocus'>
require([
'dstore/RequestMemory',
'dgrid/OnDemandGrid'
], function (RequestMemory, OnDemandGrid) {
// Create an instance of OnDemandGrid referencing the store
var dom = require('dojo/dom');
console.log("onFocus event for CustomersGrid ContentPane");
dom.byId('studentLastname').value = 'test onFocus event';
var grid = new OnDemandGrid({
collection: new RequestMemory({ target: 'hof-batting.json' }),
columns: {
first: 'First Name',
last: 'Last Name',
totalG: 'Games Played'
}
}, 'grid');
grid.startup();
});
</script>
</div>
I could make it work by:
setting the id of the div to 'grid'
adding a "Click me" span (or I had nothing to focus on)
changing the event name from 'onFocus' to 'focus'
Then, the grid appears when you click on the 'Click me' text (to activate focus).
Below the corresponding full source page (for my environment):
<!DOCTYPE HTML><html lang="en">
<head>
<meta charset="utf-8">
<title>Neal Walters stask overflow test</title>
<link rel="stylesheet" href="dojo-release-1.12.2-src/dijit/themes/claro/claro.css" media="screen">
<link rel="stylesheet" href="dojo-release-1.12.2-src/dgrid/css/dgrid.css" media="screen">
</head>
<body class="claro">
<div id='grid' data-dojo-type="dijit/layout/ContentPane" data-dojo-props='title:"CustomersGrid"'>
<span>click me!</span>
<script type='dojo/on' data-dojo-event='focus'>
require([
'dstore/RequestMemory',
'dgrid/OnDemandGrid'
], function (RequestMemory, OnDemandGrid) {
// Create an instance of OnDemandGrid referencing the store
var dom = require('dojo/dom');
console.log("onFocus event for CustomersGrid ContentPane");
//dom.byId('studentLastname').value = 'test onFocus event';
var grid = new OnDemandGrid({
collection: new RequestMemory({ target: 'hof-batting.json' }),
columns: {
first: 'First Name',
last: 'Last Name',
totalG: 'Games Played'
}
}, 'grid');
grid.startup();
});
</script>
</div>
<script src="dojo-release-1.12.2-src/dojo/dojo.js" data-dojo-config="async:true"></script>
<script type="text/javascript">
require(["dojo/parser", "dojo/domReady!"],
function(parser){
parser.parse();
});
</script>
</body>
The above is using declarative syntax. Alternatively, you may consider going programmatic, as in the source code below where the grid appears on loading the page. Also whereas with the declarative syntax above a breakpoint inside the script is ignored (using firefox), it is activated as expected with the programmatic syntax:
<!DOCTYPE HTML><html lang="en">
<head>
<meta charset="utf-8">
<title>Neal Walters stask overflow test</title>
<link rel="stylesheet" href="dojo-release-1.12.2-src/dijit/themes/claro/claro.css" media="screen">
<link rel="stylesheet" href="dojo-release-1.12.2-src/dgrid/css/dgrid.css" media="screen">
</head>
<body class="claro">
<div id='grid' data-dojo-type="dijit/layout/ContentPane" data-dojo-props='title:"CustomersGrid"'></div>
<script src="dojo-release-1.12.2-src/dojo/dojo.js" data-dojo-config="async:true"></script>
<script>
require([
'dstore/RequestMemory',
'dgrid/OnDemandGrid'
], function (RequestMemory, OnDemandGrid) {
// Create an instance of OnDemandGrid referencing the store
var dom = require('dojo/dom');
console.log("onFocus event for CustomersGrid ContentPane");
//dom.byId('studentLastname').value = 'test onFocus event';
var grid = new OnDemandGrid({
collection: new RequestMemory({ target: 'hof-batting.json' }),
columns: {
first: 'First Name',
last: 'Last Name',
totalG: 'Games Played'
}
}, 'grid');
grid.startup();
});
</script>
</body>
I have defined dgrid and a button for removing row:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="http://cdn.rawgit.com/SitePen/dgrid/v1.1.0/css/dgrid.css" media="screen" />
</head>
<body class="claro">
<div id="container"></div>
<button id="remove">Remove</button>
<script type="text/javascript">
var dojoConfig = {
async: true,
packages: [
{ name: 'dgrid', location: '//cdn.rawgit.com/SitePen/dgrid/v1.1.0' },
{ name: 'dstore', location: '//cdn.rawgit.com/SitePen/dstore/v1.1.1' }
]
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<script type="text/javascript">
require([
'dojo/_base/declare',
'dojo/on',
"dojo/dom",
"dstore/Memory",
"dstore/Trackable",
'dstore/SimpleQuery',
'dgrid/Grid',
'dgrid/extensions/Pagination',
'dgrid/extensions/DijitRegistry',
'dojo/domReady!'
],
function(declare, on, dom, Memory, Trackable, SimpleQuery, Grid, Pagination, DijitRegistry) {
var data = [];
for (var i = 1; i <= 500; i++) {
data.push({id:i,name: 'Name '+i, value: i});
}
var Store = declare([Memory, SimpleQuery, Trackable]);
var myStore = new Store({data:data});
var MyGrid = declare([Grid, Pagination]);
var grid = new MyGrid({
collection: myStore,
columns: {
'id' : 'Id',
'name' : 'Name',
'value' : 'Value'
},
className: "dgrid-autoheight",
showLoadingMessage: false,
noDataMessage: 'No data found.'
}, 'container');
grid.startup();
on(dom.byId('remove'),'click',function() {
myStore.remove(10);
});
});
</script>
</body>
</html>
The dgrid shows up, you can sort it, edit name or value.
The problem is, that when you click on the "remove" button, row is deleted, but then, at the end of the gird is 9x written: "No data found" and the dgrid stops to work (you cant delete any other row).
If you set showLoadingMessage: to true, then everything works without a problem.
Edit: I have simplified the example. Problem persists.
The grid may have been encountering error while updating the row data after the row has been removed. As the editor tries to update the row after the button loses focus. Try using the grid.removeRow method to remove the row. It might still encounter some other issues, but worth a try.
Editor might not be the best solution to achieve what your are trying to do.
User renderCell to add button to the grid, to remove the row/record. This might be a better solution.
Update: Just refresh the grid that should solve the problem.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="http://cdn.rawgit.com/SitePen/dgrid/v1.1.0/css/dgrid.css" media="screen" />
</head>
<body class="claro">
<div id="container"></div>
<button id="remove">Remove</button>
<script type="text/javascript">
var dojoConfig = {
async: true,
packages: [
{ name: 'dgrid', location: '//cdn.rawgit.com/SitePen/dgrid/v1.1.0' },
{ name: 'dstore', location: '//cdn.rawgit.com/SitePen/dstore/v1.1.1' }
]
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<script type="text/javascript">
require([
'dojo/_base/declare',
'dojo/on',
"dojo/dom",
"dstore/Memory",
"dstore/Trackable",
'dstore/SimpleQuery',
'dgrid/Grid',
'dgrid/extensions/Pagination',
'dgrid/extensions/DijitRegistry',
'dojo/domReady!'
],
function(declare, on, dom, Memory, Trackable, SimpleQuery, Grid, Pagination, DijitRegistry) {
var data = [];
for (var i = 1; i <= 500; i++) {
data.push({id:i,name: 'Name '+i, value: i});
}
var Store = declare([Memory, SimpleQuery, Trackable]);
var myStore = new Store({data:data});
var MyGrid = declare([Grid, Pagination]);
var grid = new MyGrid({
collection: myStore,
columns: {
'id' : 'Id',
'name' : 'Name',
'value' : 'Value'
},
className: "dgrid-autoheight",
showLoadingMessage: false,
noDataMessage: 'No data found.'
}, 'container');
grid.startup();
on(dom.byId('remove'),'click',function() {
myStore.remove(10);
grid.refresh();
});
});
</script>
</body>
</html>
I have just started with sencha touch,really impressed with sencha documentation and its native feel. I was trying out this link. But i got error in between and i got this error in console "The following classes are not declared even if their files have been loaded: 'Ext.panel'. Please check the source code of their corresponding files for possible typos: 'touch/src/panel.js". i am new to MVC framework so i am not able to find where i went wrong.
And is it necessary to get good knowledge of ExtJs before trying out Sencha Touch?
Here is my code
App.js
Ext.Loader.setPath({
'Ext': 'touch/src'
});
Ext.application({
name: 'hello',
requires: [
'Ext.MessageBox'
],
views: [
'Main','Home'
],
icon: {
'57': 'resources/icons/Icon.png',
'72': 'resources/icons/Icon~ipad.png',
'114': 'resources/icons/Icon#2x.png',
'144': 'resources/icons/Icon~ipad#2x.png'
},
isIconPrecomposed: true,
startupImage: {
'320x460': 'resources/startup/320x460.jpg',
'640x920': 'resources/startup/640x920.png',
'768x1004': 'resources/startup/768x1004.png',
'748x1024': 'resources/startup/748x1024.png',
'1536x2008': 'resources/startup/1536x2008.png',
'1496x2048': 'resources/startup/1496x2048.png'
},
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
Ext.Viewport.add(Ext.create('hello.view.Main'));
},
onUpdated: function() {
Ext.Msg.confirm(
"Application Update",
"This application has just successfully been updated to the latest version. Reload,
function(buttonId) {
if (buttonId === 'yes') {
window.location.reload();
}
}
);
}
});
Main.js
Ext.define('hello.view.Main', {
extend: 'Ext.tab.Panel',
requires: [
'Ext.TitleBar'
],
config: {
tabBarPosition: 'bottom',
items: [
{
xtype:'homepanel'
}
]
}
});
Home.js
Ext.define('Hello.View.Home',{
extend:'Ext.panel',
xtype:'homepanel',
config:{
title:'Home',
iconCls:'home',
html: [
'<img src="http://staging.sencha.com/img/sencha.png" />',
'<h1>Welcome to Sencha Touch</h1>',
"<p>You're creating the Getting Started app. This demonstrates how ",
"to use tabs, lists, and forms to create a simple app</p>",
'<h2>Sencha Touch</h2>'
].join("")
}
});
index.html
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
<meta charset="UTF-8">
<title>hello</title>
<style type="text/css">
</style>
<!-- The line below must be kept intact for Sencha Command to build your application ->
<script id="microloader" type="text/javascript" src="touch/microloader/development.js"> </script>
<script type="text/javascript" src="app/view/Home.js"></script>
</head>
<body>
<div id="appLoadingIndicator">
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
Exactly as the error says. The class name is Ext.Panel, not Ext.panel.