For this tutorial we refer to your LuCI installation directory as `lucidir` (`/usr/lib/lua/luci` on your OpenWRT device) and assume your LuCI installation is reachable through your webserver via `http://192.168.1.1/cgi-bin/luci`.
- Add configurations to your dev studio which will delete the luci cache (detailed below) and then open a browser window to your routers' configuration page in order to see your module/application.
When testing, if you have edited index files, be sure to remove the folder `/tmp/luci-modulecache/*` and the file(s) `/tmp/luci-indexcache*`, then refresh the LUCI page to see your edits.
*`path` is a table that describes the position in the dispatching tree: For example a path of `{"foo", "bar", "baz"}` would insert your node in `foo.bar.baz`.
*`target` describes the action that will be taken when a user requests the node. There are several predefined actions, of which the 3 most important (call, template, cbi) are described later on this page
And now visit the path `/cgi-bin/luci/click/here/now` (`http://192.168.1.1/luci/click/here/now` if you are using the development environment) in your browser.
As you may or may not know: CGI specification requires you to send a `Content-Type` header before you can send your content. You will find several shortcuts (like the one used above) as well as redirecting functions in the module `luci.http`
If you only want to show the user text or some interesting family photos, it may be enough to use an HTML-template.
These templates can also include some Lua code but be aware that writing whole office-suites by only using these templates might be considered "dirty" by other developers.
It creates a formulae based user interface and saves its contents to a specific UCI config file.
You only have to describe the structure of the configuration file in a CBI model file and Luci does the rest of the work.
This includes generating, parsing and validating an XHTML form and reading and writing the UCI file.
So let's be serious at least for this paragraph and create a practical example `lucidir/model/cbi/myapp-mymodule/netifaces.lua` with the following contents:
```lua
m = Map("network", "Network") -- We want to edit the uci config file /etc/config/network
s = m:section(TypedSection, "interface", "Interfaces") -- Especially the "interface"-sections
s.addremove = true -- Allow the user to create and remove the interfaces
function s:filter(value)
return value ~= "loopback" and value -- Don't touch loopback
end
s:depends("proto", "static") -- Only show those with "static"
s:depends("proto", "dhcp") -- or "dhcp" as protocol and leave PPPoE and PPTP alone
p = s:option(ListValue, "proto", "Protocol") -- Creates an element list (select box)
p:value("static", "static") -- Key and value pairs
p:value("dhcp", "DHCP")
p.default = "static"
s:option(Value, "ifname", "interface", "the physical interface to be used") -- This will give a simple textbox
s:option(Value, "ipaddr", translate("ip", "IP Address")) -- Yes, this is an i18n function ;-)
s:option(Value, "netmask", "Netmask"):depends("proto", "static") -- You may remember this "depends" function from above
mtu = s:option(Value, "mtu", "MTU")
mtu.optional = true -- This one is very optional
dns = s:option(Value, "dns", "DNS-Server")
dns:depends("proto", "static")
dns.optional = true
function dns:validate(value) -- Now, that's nifty, eh?
return value:match("[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+") -- Returns nil if it doesn't match otherwise returns match
end
gw = s:option(Value, "gateway", "Gateway")
gw:depends("proto", "static")
gw.rmempty = true -- Remove entry if it is empty
return m -- Returns the map
```
and of course remember to add something like this to your module's `index`-Function.