Creating a Mithril.js Single Page Application (SPA) using a JSON data source: A

I am currently working on creating a single page application (SPA) using Mithril.js. While I have come across some helpful tutorials like the one here and on the official Mithril homepage, I am struggling to combine the concepts from both sources effectively.

Below is a modified example inspired by Dave's guide...

function btn(name, route){
  var click = function(){ m.route(route); };
  return m( "button", {onclick: click}, name );
}
function Page(content){
  this.view = function(){
    return [         
      m("page", 
        m("span", Menu.menu()) 
      ) 
      , m("div", content)
    ];
  }
}
var Menu = { 
  menu: function(){
    return [
      btn("Home",   "/home")
    , btn("About",  "/about")
    ];
  }
};
var page_Home =  new Page("The home of the Hobbits. Full of forests and marshes.");
var page_About = new Page(["The blighted home of Sauron. Scenic points of interest include:"]);

  m.route(document.body, "/home", {
    "/home": page_Home,
    "/about": page_About
  });

Here is my JSON file:

[
 {
  "id":1,
  "title": "Home",
  "url": "/home",
  "content":"This is home page"
 },{
  "id":2,
  "title": "About",
  "url": "/about",
  "content":"This is about page"
 },{
  "id":3,
  "title": "Gallery",
  "url": "/gallery",
  "content":"This is gallery page"
 }
]

My attempt at combining the JSON data with the previous example:

//model
var PageSource = {
  list: function() {
    return m.request({method: "GET", url: "pages.json"});
  }
};
var pages = PageSource.list();

var App = {
  //controller
  controller: function() {
    return {
      menu: pages
    , rotate: function() { pages().push(pages().shift()); }
    , id: m.route.param(pages.url)
    }
  },

  //view
  view: function(ctrl) {
    return  [
      m("header"
        , m("h1", "Page Title")
        , m("span",
            ctrl.menu().map(function(item) { 
              var click = function(){ 
                console.log (item.url);
                m.route(item.url); 
              };               
              return [
                  m("button", {onclick: click}, item.title)        
              ];
            })
          )
        , m("hr")
       )
    ,  m("button", {onclick: ctrl.rotate}, "Rotate links" )
    ,  m("p", ctrl.content ) //CONTENT
    ];
  }
};

//initialize
  m.route(document.body, "/home", {
    "/:id": App
  });

And now for my questions: - "How can I fetch data from a JSON file and display it in a div based on the selected button (routing)?" - "When using m.route, my entire view refreshes, but I only want to reload the changed div. How can I achieve this?" I would appreciate any help, as I am really enjoying working with Mithril.js so far.

Answer №1

You're getting warmer.

  1. Your router setup seems to be duplicated, with the later configuration overwriting the initial one. Make sure to define your routes using m.route only once and place it after any other code declarations.

  2. When trying to access ctrl.content in your App view, it will come up as undefined because you haven't set a content property in the App controller. Be sure to include the desired content in the object returned by the App controller.

Answer №2

Thanks to @dcochran, I was able to accomplish the following:

//model
var PageSource = {
  list: function() {
    return m.request({method: "GET", url: "pages.json"});
  }
};
var pages = PageSource.list();
var id = m.prop()
  , url = m.prop()
  , title = m.prop()
  , content = m.prop();

var App = {
//controller
  controller: function() {
    return {
      menu: pages
    , rotate: function() { pages().push(pages().shift()); }
    }
  },

//view
  view: function(ctrl) {
    return  [
      m("header"
        , m("h1", "Page title")
        , m("span",
            ctrl.menu().map(function(item) { 
              return [ btn(item.title, item.url) ];
              function btn(name, route){
                var isCurrent = (url === route);
                var click = function(){ 
                  //m.route(route); 
                  id = item.id;
                  url = item.url; 
                  content = item.content;
                  title = item.title;
                };
                return m(
                  "button"+(isCurrent ? ".active" : ""), 
                  {onclick: click}, 
                  name
                );
              }
            })
          )
        , m("hr")
       )
    ,  m("button", {onclick: ctrl.rotate}, "Rotate links" )
    ,  m(".page", content )
    ];
  }
};
//initialize
m.route.mode = "hash";
m.route(document.body, "/home", { 
  "/:url": App
})

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to transform an array of objects into a single string in JavaScript?

After receiving the input from req.body, it looks like this: [ { "Name": "Test_1", "Level 1": "Story_1", "Level 2": "Story_1.1" }, { "Name": & ...

WebGL Error: An invalid operation occurred while trying to use the uniformMatrix4fv function. The error code [WebGL-00000A18072FEA00

Currently, I am working on an app that showcases 360° images and I rely on the BabylonJS library for this feature. The navigation bar helps me switch between different 360 locations within the application. However, whenever I try to change the 360 image ...

Simple method for converting pixel values to em units

I'm searching for a simple method to incorporate a line of code into one of my plugins in order to convert specific pixel values into em values. My project's layout requires the use of ems, and I'd prefer not to rely on external plugins for ...

Am I on the right track with incorporating responsiveness in my React development practices?

Seeking advice on creating a responsive page with React components. I am currently using window.matchMedia to match media queries and re-rendering every time the window size is set or changes. function reportWindowSize() { let isPhone = window.matchMed ...

Having trouble selecting a default option in a dynamically populated select dropdown using ng-model in the dropdown

For my Angularjs application, I needed to dynamically return a select drop down with its selected option. To accomplish this, I implemented the following function: function getCellRendererMapping(data) { if (data.order == 6) { return funct ...

A guide on setting up dual observables in Angular 2

Currently, I am implementing Observable in angular 2 with rxjs. As part of my demonstration, I have utilized fromEvent in a Plunker. Here is the link to my demo: https://plnkr.co/edit/zkgEcdn21CvIKoOycUOy?p=preview In this demo, I have included two input ...

converting HTML values to TypeScript

I'm a beginner with Angular and could use some assistance. Currently, I have two components - one for the index and another for navigation. Within the index component, there are subcomponents that change based on the value of a variable called produ ...

Retrieving JSON data from a URL with PHP

Attempting to retrieve JSON data from the following URL: $search_data&format=json&nojsoncallback=1 The information I am aiming to obtain based on the above link is as follows: { "places": { "place": [ { ...

Using Express middleware in a TypeScript Express application

I'm currently converting the backend of an ExpressJS application to Typescript. While working on the auth.routes.ts file, I encountered an issue with the middleware (authMiddleware). It seems like there might be a typing error, as the same code in the ...

Remove the export statement after transpiling TypeScript to JavaScript

I am new to using TypeScript. I have a project with Knockout TS, and after compiling it (using the Intellij plugin to automatically compile ts to js), this is my sample.ts file: import * as ko from "knockout"; ko; class HelloViewModel { language: Kn ...

Extract information from an HTML table into PHP

I have an HTML table that is generated dynamically and I am looking to extract the data from it using the POST method. Is there a way to accomplish this? Are there any alternative methods you would suggest for achieving this goal? Below is a basic example ...

Why does JSON.parse() in my AJAX response return undefined?

I've been developing a small app that sends an AJAX GET request to a URL, which responds with JSON using the PHP `json_encode()` function. However, when I attempt to access individual values from the JSON response, it indicates undefined. Surprisingly ...

I am in need of a blank selection option using an md-select element, and I specifically do not want it to be

I'm currently utilizing Angular Material with md-select and I am in need of creating a blank option that, when selected, results in no value being displayed in the select dropdown. If this blank option is set as required, I would like it to return fal ...

What is the best way to recreate WordPress categories using static HTML pages?

As I consider converting my WordPress website to static HTML pages, I'm planning on editing them in tools like Responsive Site Designer, Dreamweaver, or SublimeText. My main concern is how I will organize content into categories without the convenien ...

React: Show input value on button click

I have been working on a React form that displays the entered input value in a controlled input element only after the user hits the submit button, rather than updating it constantly as the user types. Here is my current solution using conditional renderin ...

Is it possible to utilize the returned value of a function within an if statement?

Is there a way to return the result of a function without needing to declare a variable? Can you return the result of a function in a single line? How can you return the result of a function inside an if statement? Is it possible to use a function's ...

Tips for passing a JavaScript array to an MVC controller

In my asp.net application, I have implemented a functionality where users can order food. Additionally, there is an admin page where admins can login and create a menu for a specific week. I have successfully developed the "Menu maker" feature where all me ...

I had hoped to remove just one item, but now the entire database is being erased

I present it in this way <tr v-for="(foodItem, index) in filteredFoodItems"> <td>{{ foodItem.name }}</td> <td>{{ foodItem.price | currency('£') }}</td> <td>{{ foodItem.category }}< ...

Mastering the utilization of API routes within the Next JS 13 App Router framework

As a newcomer to React JS and Next.js, I recently made the switch from using the Page Router API in Next.js to utilizing the new App Router introduced in Next.js 13. Previously, with the Page Router, creating a single GET request involved nesting your "JS ...

selecting arrays within arrays according to their date values

With an array of 273 arrays, each containing data about a regular season NFL football game, I am looking to categorize the games by week. In total, there are 17 weeks in the NFL season that I want to represent using separate arrays. The format of my array ...