Unable to access model from core in sapUI5 - model-view-controller

Follow up to related question
here
For whatever reason I'm unable to access my model in my xml view when it's set through sap.ui.getCore().setModel(). If I set it on the this.getView() I have no problems at all.
My view XML
<mvc:View controllerName="ca.toronto.rcsmls.webapp.controller.Login"
xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" xmlns:l="sap.ui.layout">
<Page title="{i18n>loginPageTitle}">
<content>
<Panel id="loginPanel" busyIndicatorDelay="0"
headerText="{i18n>loginPanelTitle}" class="sapUiResponsiveMargin loginPanel"
width="auto">
<l:VerticalLayout width="100%">
<Input type="Text" placeholder="{i18n>loginUidHolder}" value="{/mlsUser/uid}" />
<Input type="Password" placeholder="{app>/Password}"
value="{/mlsUser/password}" />
<Button text="{i18n>loginButtonText}" press="doLogin"
class="sapUiSmallMarginEnd customBold" width="100%" />
</l:VerticalLayout>
</Panel>
</content>
</Page></mvc:View>
My controller JS contains this for setModel()
onInit : function() {
sap.ui.getCore().setModel(new sap.ui.model.json.JSONModel("webapp/controller/app.json"), "app");
}
Again, if I set the model to this.getView().setModel() instead of getCore() XML and controller work fine together. I also added data-sap-ui-xx-bindingSyntax="complex" to my index.html but that didn't seem to make a difference. Any help would be appreciated.
Edited to include more information
My Component.js
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/model/json/JSONModel",
], function (UIComponent, JSONModel) {
"use strict";
return UIComponent.extend("ca.toronto.rcsmls.webapp.Component", {
metadata : {
manifest: "json"
},
init : function () {
// call the init function of the parent
UIComponent.prototype.init.apply(this, arguments);
// set data model
var oData = {
mlsUser : {
uid : "",
password : "",
}
};
var oModel = new JSONModel(oData);
this.setModel(oModel);
// create the views based on the url/hash
this.getRouter().initialize();
}
});
});
My manifest.json
{
"_version": "1.1.0",
"sap.app":
{
"_version": "1.1.0",
"id": "ca.toronto.rcsmls",
"type": "application",
"i18n": "i18n/i18n.properties",
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"applicationVersion":
{
"version": "1.0.0"
},
"ach": "CA-UI5-DOC"
},
"sap.ui":
{
"_version": "1.1.0",
"technology": "UI5",
"deviceTypes":
{
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes":
[
"sap_bluecrystal"
]
},
"sap.ui5":
{
"_version": "1.1.0",
"rootView": "ca.toronto.rcsmls.webapp.view.App",
"dependencies":
{
"minUI5Version": "1.30",
"libs":
{
"sap.m":
{
}
}
},
"config":
{
"authenticationService": "http://172.21.226.138:9080/RcsMlsSvc/jaxrs/user/authenticate/",
"assignedWorkService": "http://172.21.226.138:9080/RcsMlsSvc/jaxrs/mls/searchAssignedWork"
},
"models":
{
"i18n":
{
"type": "sap.ui.model.resource.ResourceModel",
"settings":
{
"bundleName": "ca.toronto.rcsmls.webapp.i18n.i18n"
}
}
},
"routing":
{
"config":
{
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "ca.toronto.rcsmls.webapp.view",
"controlId": "root",
"controlAggregation": "pages"
},
"routes":
[
{
"pattern": "",
"name": "login",
"target": "login"
},
{
"pattern": "work",
"name": "work",
"target": "work"
}
],
"targets": {
"login": {
"viewName": "Login"
},
"work": {
"viewName": "Work"
}
}
},
"resources":
{
"css":
[
{
"uri": "css/style.css"
}
]
}
}
}
Model app.json
{
"BaseURL": "https://smp-pNNNNNNtrial.hanatrial.ondemand.com",
"ES1Root": "https://sapes1.sapdevcenter.com",
"AppName": "qmacro.myfirst",
"Username": "yourusername",
"Password": "yourpassword"
}
I found an example where core binding works here. It is a much simpler application. I'm still trying to figure out the what the differences are between this project and mine

I was made aware of this question by a similar question on Github
By default, UI5 components don't inherit models and binding contexts from their environment (the ComponentContainer where they are placed). This was done for the sake of isolation.
You can change that default behavior by setting the property propagateModel:true for the container:
new sap.ui.core.ComponentContainer({
name: "ca.toronto.rcsmls.webapp.Component",
propagateModel: true
}).placeAt("content");
Documentation for propagateModel can be found in the API reference as well as in the UI5 developer guide (the corresponding paragraph in the latter page was only added recently, it was not available when you raised your question).
But when the model is created in the scope of the component and shall be used inside the component, then there should be no need to add it to the Core. Just assign it to the component to share it between views inside that component:
Assign it either from some method in a view controller
onInit : function() {
this.getOwnerComponent().setModel(
new sap.ui.model.json.JSONModel(
"webapp/controller/app.json"), "app");
}
or during init of the Component.js itself
init : function() {
// create and set model to make it available to all views
this.setModel(
new sap.ui.model.json.JSONModel(
"webapp/controller/app.json"), "app");
// never forget to call init of the base class
UIComponent.init.apply(this, arguments);
}
The most modern approach is to configure the model in the manifest.json and to let the framework instantiate an assign it. See Walkthrough Tutorial - Step 10: Descriptor for Applications for an example.
Using any of these approaches, there should not even be a need to read and set the model in another view, as long as that view is a descendant of the component (part of the control tree returned by createContent).

I experienced the same behavior.
If I create a simple one-file application, without any complex UI elements, the core-based binding works like a charm.
If I create a complex container, like an App with a shell, this kind of binding will not work anymore. It seems that these containers hide the global model from the view.
As a workaround I used the following code snippet:
this.getView().setModel(sap.ui.getCore().getModel(modelName), "modelName");
Or even you can bind the model directly to the control where you want to use.
None of them are the best solution if you have to use the global model in several view/control, but that's working for me.

I the view above only the placeholder of the password field is using your app model. If this placeholder is not filled correctly then I guess the json file could not be loaded or the content is not matching the binding path you use in your view for the placeholder property of the password field. To find out more please post also the content of your json file. It should look somehow like this:
{ "Password" : "Enter your password", ... }
So according to the binding in the view there must be "Password" property at the root level of the data object.
Below you find a running example that should help you. As you can see you it work like a charm, so you can easily put a named model onto the Core and reference it in your view.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SAPUI5 single file template | nabisoft</title>
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"></script>
<!-- use "sync" or change the code below if you have issues -->
<!-- XMLView -->
<script id="myXmlView" type="ui5/xmlview">
<mvc:View
controllerName="MyController"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:l="sap.ui.layout"
xmlns:mvc="sap.ui.core.mvc">
<App>
<Page title="My Page Title">
<content>
<Panel id="loginPanel" busyIndicatorDelay="0"
headerText="My Login Panel Title" class="sapUiResponsiveMargin loginPanel"
width="auto">
<l:VerticalLayout width="100%">
<Input type="Text" placeholder="{Enter User ID}" value="{/mlsUser/uid}" />
<Input type="Password" placeholder="{app>/Password}" value="{/mlsUser/password}" />
<Button text="{Login}" press="doLogin" class="sapUiSmallMarginEnd customBold" width="100%" />
</l:VerticalLayout>
</Panel>
</content>
</Page>
</App>
</mvc:View>
</script>
<script>
sap.ui.getCore().attachInit(function () {
"use strict";
//### Controller ###
sap.ui.controller("MyController", {
onInit : function () {
var oData, oModel;
// 1. app model is only used for the placeholder field in the view
oData = {
Password : "Enter your password"
};
oModel = new sap.ui.model.json.JSONModel(oData);
sap.ui.getCore().setModel(oModel, "app");
// 2. default model is used in the view as well
oData = {
mlsUser : {},
Login : "Login now"
};
oModel = new sap.ui.model.json.JSONModel(oData);
sap.ui.getCore().setModel(oModel);
// 3. we need this because of the relative binding
// of the text property of the login button
this.getView().bindElement("/");
}
});
//### THE APP: place the XMLView somewhere into DOM ###
sap.ui.xmlview({
viewContent : jQuery("#myXmlView").html()
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>
In this thread some people have mentioned that "sap.ui.getCore() works with small stuff, but for whatever reason not in more complex applications".
#Marc has also posted the right link to the API docs, where you can find the following:
A ManagedObject inherits models from the Core only when it is a
descendant of an UIArea
Of course, you have to know what this means in order write code that does what you expect. Here is a little example that tells you what could happen in case you have a small "misunderstanding" (see below).
The code below creates two instances of sap.m.Text and binds their text properties to a JSONModel, which is available as a named model "core" directly on the Core (retrieved with sap.ui.getCore()). There are 2 buttons, one for each sap.m.Text instance. In the corresponding press handlers of the buttons I just display the text property of the corresponding sap.m.Text instance. As you can see, both sap.m.Text instances are bound to the same property in the JSONModel. However, only the second sap.m.Text is added to the DOM.
Now the interesting part, which might be related to the confusion of this thread:
Only the text property of the second sap.m.Text control contains the expected text "Hello World" from the JSONModel. The text property of the first sap.m.Text control does not have the value "Hello World" from the model! This is expected behavior of SAPUI5 and it is documented! So I guess in case you face similar issues in your own "complex" app, then it might be quite probable that you have a hard to find bug related to this "expected" behavior.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SAPUI5 single file template | nabisoft</title>
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"></script>
<!-- use "sync" or change the code below if you have issues -->
<script>
sap.ui.getCore().attachInit(function () {
sap.ui.define([
"sap/m/Text",
"sap/m/Button",
"sap/ui/model/json/JSONModel"
], function (Text, Button, JSONModel) {
"use strict";
var oModel = new JSONModel({
hello : "Hello World"
});
sap.ui.getCore().setModel(oModel, "core");
// not in DOM
var oText1 = new Text({
text : "{core>/hello}"
});
//oText1.placeAt("text1"); // uncomment this to enable the binding
// add to DOM
var oText2 = new Text({
text : "{core>/hello}"
});
oText2.placeAt("text2");
// action buttons to display text property of text controls
new Button({
text : "show oText1",
press : function(){
alert("oText1.getText() = " + oText1.getText());
}
}).placeAt("btn1");
new Button({
text : "show oText2",
press : function(){
alert("oText2.getText() = " + oText2.getText());
}
}).placeAt("btn2");
});
});
</script>
</head>
<body class="sapUiBody">
<div id="text1"></div>
<div id="text2"></div>
<span id="btn1"></span>
<span id="btn2"></span>
</body>
</html>

sap.ui.getCore() and this.getView() return not the same object i think it's obvious why this doesn't work.
You are trying to get a object(model) from another object (the core) although the desired model is bound to another object(the view)
it's like i have two colored boxes (one red, one blue) and im trying to get the color red from the blue colored box
Here is an similar issue but the cause in this one depends on the id handling of the views in the UI5 framework:
https://scn.sap.com/thread/3551589
You can see the core and the view does not return the same object.
Also checkout the data binding section on the openui5 website: https://openui5beta.hana.ondemand.com/#docs/guide/e5310932a71f42daa41f3a6143efca9c.html
Create Model in components.js:
var oModel= new sap.ui.model.json.JSONModel;
oModel.loadData("webapp/controller/app.json");
this.setModel(oModel, "app");
Get Model:
This will create a reference to the model which has been created in the Components.js
var oModel= this.getView().getModel("app");
Refer to the model with "{modelName(app)>desiredProperty}"
<Input type="Password" placeholder="{app>Password}"
value="{app>mlsUser/password}" />
could you post your json content?
Hope this was helpful

Related

Lazyload image in Vue/Nuxt gallery component

I'm trying to create a simple gallery component where if you click on some image a Light-Box will appear where you can see full size photo and have options like next and previous photo or close the Light-Box.
Currently When I need to change the image to next or previous I change the src of the img-tag and it works.
Here comes my problem. I want to lazy load my images. I use lazysizes in my project.
So the simple implementation to have an image to load is to add the class "lazyload" and to pass the property data-src instead of src.
However if I change to data-src my methods for next and previous image are not working.
< script >
export default {
props: {
data: {
type: Array,
required: true,
},
},
data: () => ({
visible: false,
currentImage: 0,
}),
methods: {
Toggle(index) {
this.currentImage = index
this.visible = !this.visible
},
Next() {
if (this.currentImage !== this.data.length - 1) this.currentImage++
},
Prev() {
if (this.currentImage !== 0) this.currentImage--
},
},
} <
/script>
<template>
<div id="gallery" class="gallery">
<!-- images grid -->
<div v-for="(item, i) in data" :key="'gallery-image' + i" class="image">
<img :src="item.image.thumbnail.url" #click.native="Toggle(i)" class="lazyload"/>
</div>
<!-- image lighbox on click -->
<div v-if="visible" class="lightbox">
<Icon class="cancel" #click="Toggle()"/>
<Icon name="left" :class="{ disable: currentImage == 0 }" #click="Prev()"/>
<img :src="data[currentImage].image.url" class="lazyload"/>
<Icon name="right" :class="{ disable: currentImage == data.length - 1 }" #click="Next()"/>
</div>
</div>
</template>
UPDATE
I forgot to add crucial code. To implement lazysizes in a Nuxt project we need to add in nuxt.config.js the fallowing code. You can read more here.
build: {
extend(config, { isClient, loaders: { vue } }) {
vue.transformAssetUrls.img = ['data-src', 'src']
},
},
As I investigate in the developer tools I found that when triggering click for method like Next image, the src of the image does not change, only the data-src. I'm guessing I need a way to trigger this transform so that everything can work as expected.
Also, on top of my comment, I do recommend looking into the official nuxt image module which do have native lazy loading out of the box: https://image.nuxtjs.org/components/nuxt-img
You could maybe combo this with some simple lightbox that does the trick for you. I've used vue-silentbox before, it is working pretty well.
You can have that kind of code there
<silent-box :gallery="photosToDisplay">
<template #silentbox-item="{ silentboxItem }">
<img :src="silentboxItem.src" :key="silentboxItem.id" />
</template>
</silent-box>
So, I guess that you could totally swap img by a nuxt-img there, and have it lazy-loaded.
The images are not lazy-loaded in the project, but here is a small project that I did to try out the lightbox if you want to quickly look how it renders (URL in the top right corner).
Probably this is not the most elegant way to do it . I force re-render to my image component. You need to assign a key value to component and whenever the value changes a new instance creates of the component.

Changing fields updates livewire #entangle field

I have a component that is entangling a livewire property.
<div x-data="{show: #entangle($attributes->wire('model'))}>
<form>
<input type="checkbox" wire:model.defer="story.show_name" name="show_name" />
</form>
</div>
I have a form within this component. If I update any field within the form it will send an update to the server bug it also modifies the wire:model. An example would be a checkbox. If I uncheck it then the component hides.
Example:
[
{
"type": "syncInput",
"payload": {
"name": "story.show_name",
"value": false
}
},
{
"type": "syncInput",
"payload": {
"name": "show",
"value": false
}
}
]
Any idea why this would suddenly be capturing all input/change events?
The problem was due to me adding all attributes to the component like so {{$attributes}}. This would add wire:model="show" to the element. Since my component wasn't an input field and just a div it would then accept all input events.
I replaced {{$attributes}} with {{$attributes->except('wire:model')}} to fix the problem.

SAP UI5 XML View Tiles Icon not working

I have a XML View:
<mvc:View height="100%" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m" controllerName="my.own.controller">
<App>
<Page showHeader="false" enableScrolling="false">
<TileContainer id="container" tileDelete="handleTileDelete" tiles="{/TileCollection}">
<StandardTile icon="sap-icon://{icon}" number="{number}" title="{title}" info="{info}" infoState="Success" />
</TileContainer>
<footer>
</footer>
</Page>
</App>
And I have a js:
function initialLoad(){
// create some dummy JSON data
var data = {
"TileCollection" : [{
"icon":"history",
"number":"3",
"title" : "Project History",
"info": "click to view",
"infoState" : "Success"
}]
};
// instantiate the View
sap.ui.localResources("XMLViews");
var app = new sap.m.App({initialPage:"welcome"});
var myView = sap.ui.xmlview({id:"welcome", viewName:"XMLViews/welcome"});
app.addPage(myView);
// create a Model and assign it to the View
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
myView.setModel(oModel);
// put the View onto the screen
myView.placeAt("content");}
The problem is the icon is not showing up. If I hard code in my XML view:
icon="sap-icon://history"
Then the icon is showing up correctly.
I am stuck with this problem for one day and I appreciate if you could give me some hint!
Thanks!
The Way of binding data to the icon property is incorrect. it should be in this way.
icon="{icon}"
Instead make the change in your json as below:
var data = {
"TileCollection" : [{
"icon":"sap-icon://history",
"number":"3",
"title" : "Project History",
"info": "click to view",
"infoState" : "Success"
}]
};
I think this will work.

How to use Ajax to update RenderBody() section with VS 2012 Internet Template?

I've looked at few examples where Ajax can be used to update divs or other elements with ids. I have not been able to find an example that uses Ajax with Razor views to help me with the following.
My page is a standard Menu at the top, body in the middle, and a footer. There is no real need to update the header and footer each time. In fact, my page only requires a section of the Body to be updated based on menu clicks and actionlinks on the page. I'm testing this with the Internet Template that is created using VS 2012 if that helps such that I do not have to clutter this request with a bunch of code snippets. I am using Razor views and C# for coding preferences.
So, given the default _Layout.cshtml file, how would I load the About page i.e. RenderBody() section via Ajax? I've tried adding Ajax.BeginForm(...) to my _Layout.cshtml file around one div with an UpdateTargetId that matches a div that I wrapped around the RenderBody() call, returned a partial view from my controller, but that's not quite right. What I get is my partial view only. (The About page with no menu, footer, etc. just the code on the About page)
Would someone kindly share a link that demonstrates this functionality or kindly share the code that does what I desire i.e. swap index view with about view without a full page refresh? Some explanation of what I'm missing would be nice, but I'm sure I could deduce from a solid example where I went awry. As always, your time is much appreciated.
EDIT: Using Jasen's suggestion
_Layout.cshtml
<nav>
<ul id="menu">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Ajax.ActionLink("About", "About", "Home", null, new AjaxOptions { HttpMethod = "get", UpdateTargetId = "body" }, new { })</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
</nav>
....
Inside my div id="body"
#RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
#RenderBody()
</section>
.....
HomeController.cs
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return PartialView();
}
......
Here is a simple example with jquery. The About partial gets injected into the div with id="body".
<button>About</button>
<div id="body"></div>
$(function () {
$("button").on("click", function(e) {
$.get("Home/About").done(function(result) {
$("#body").html(result);
});
});
));
Controller Action
[HttpGet]
public ActionResult About()
{
return PartialView("About");
}
About.cshtml
#{ Layout = null }
<h2>Home/About</h2>
<p>Blah... </p>
Edit: Maybe a better example is to use a link instead
#Html.ActionLink("About", "About", "Home", null, new { #class="menu-button" })
<div id="body"></div>
$(function () {
$(".menu-button").on("click", function(e) {
e.preventDefault();
var url = $(this).attr("href");
$.get(url).done(function(result) {
$("#body").html(result);
});
});
});
Edit: Without jquery you want to use Ajax.ActionLink() instead of Ajax.BeginForm()
#Ajax.ActionLink("About", "About", "Home", null, new AjaxOptions { HttpMethod = "get", UpdateTargetId = "body" }, new { })
<div id="body"></div>
In your HomeController.cs
public PartialViewResult About()
{
ViewBag.Message = "Your app description page.";
return PartialView();
}
In your _Layout.cshtml do not forget to import:
<script src="~/Content/Scripts/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="~/Content/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>

add data to dojo datagrid

I have a couple of questions related to dojo. Firstly I have an example I copied from online and ran it and it works perfectly. By the way I am working on a web application in visual studio 2010. It runs fine but my question is that I use the urls (version 1.5) from the ajax.googleapis.com and it works but as soon as I use the src="/folder/dojo.js.uncompressed.js" with the local copy (version 1.7.1) in my folder in my web app, it doesn't work. Any ideas about this.
The second question is using the datagrid example but instead of hard coding the values for the datagrid; I want to pass the results of a sql query from a database to the datagrid. Does anyone have ideas on this?
Here is code showing an attempt to use a locally stored file:
<title>The Simplest Dojo DataGrid Example of All Time</title>
<link rel="stylesheet" type="text/css"
href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css" />
<link rel="stylesheet" type="text/css"
href="/Styles/Grid.css" />
<link rel="stylesheet" type="text/css"
href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojox/grid/
resources/claroGrid.css" />
</head>
<body class="claro">
<div style="width: 600px; height: 200px">
<table id="billsGrid" dojoType="dojox.grid.DataGrid">
<thead>
<tr>
<th field="number">Number</th>
<th field="name">Name</th>
<th field="position">Position</th>
<th field="victories" width="180px">Super Bowl Victories</th>
</tr>
</thead>
</table>
</div>
<script type="text/javascript"
src="/Styles/dojo.js.uncompresses.js"
djConfig="parseOnLoad:true"></script>
<script type="text/javascript">
dojo.require("dojox.grid.DataGrid");
dojo.require("dojo.data.ItemFileReadStore");
</script>
<script type="text/javascript">
dojo.ready(function () {
var theGreatestTeamOfAllTime = {
items: [{
"number": "12",
"name": "Jim Kelly",
"position": "QB",
"victories": "0"
},
{
"number": "34",
"name": "Thurman Thomas",
"position": "RB",
"victories": "0"
},
{
"number": "89",
"name": "Steve Tasker",
"position": "WR",
"victories": "0"
},
{
"number": "78",
"name": "Bruce Smith",
"position": "DE",
"victories": "0"
}
],
identifier: "number"
};
var dataStore =
new dojo.data.ItemFileReadStore(
{ data: theGreatestTeamOfAllTime }
);
var grid = dijit.byId("billsGrid");
grid.setStore(dataStore);
});
</script>
</body>
</html>
This does not work with jscript errors cropping up.
could not load dojox/grid/DataGrid.js
To make it work locally, examine your djConfig and the script includes for dojo to ensure paths are correct, especially the baseUrl
djConfig = {
parseOnLoad: true,
baseUrl: "../dojoroot/dojo/"
}
ALso make sure you are including the correct stylesheets (all includes and stylesheets must point to the same dojo version)
Examine the Net tab in firebug to see any errors in urls
regarding your second question, dojo has a concept of datastores - these are client (javascript) side holders of data. Your server-side can return the query result in JSON (preferred), XML or any other format.
The client (javascript/html) can use AJAX to fetch this data and render it in a datagrid.
dojo has fancy stores such as queryreadstore that supports paging/lazyloading
A good place to start is the nightly tests for dojo:
http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/grid/tests/
Here are the steps I follow:
1) download dojo toolkit from http://dojotoolkit.org/download/
2) install it with your application root. Typically, in my application root directory, I have a directory called dojoroot under which i untar dojo toolkit
3) in your html, head section make sure your css links are pointing to local dojoroot. FOr xample:
4) Make sure your djConfig is correctly set:
djConfig = {
parseOnLoad: true,
baseUrl: "../../../dojoroot/dojo/"
};
note that the baseUrl is important - it is the directory in which dojo.js is located
5) for the dojo.js src include, make sure the path is correct. for example:
If there are errors, your Net tab in firebug will show them - they are usually related to path issues

Resources