我使用Angular Material来为MATLAB Production Server的Web前端示例增加了一些时尚的元素

在将用MATLAB编写的分析算法系统化时,可以通过编译并在MATLAB Production Server上部署,从而可以通过RESTful API进行交互,并可以从JavaScript调用。我试着制作了一个Web前端,并记录了下来。

范本

既有示例的文件中包含了以债券计算为主题的MATLAB代码和HTML/JavaScript样本,所以首先可以从这里开始尝试一下。

HTML/JavaScript部分

将bptool.html和calculatePrice.js复制粘贴,几乎完成,但是需要取消注释bptool.html中的

MATLAB一方

直接使用 pricecalc.m 的样本。

function price = pricecalc(face_value, coupon_payment,...
                           interest_rate, num_payments)
    M = face_value;
    C = coupon_payment;
    N = num_payments;
    i = interest_rate;

    price = C * ( (1 - (1 + i)^-N) / i ) + M * (1 + i)^-N;

点击MATLAB的“应用”->“Production Server编译器”,打开编译界面。

    • タイプ:デフォルトの「配布可能なアーカイブ」のまま。

 

    • エクスポートする関数:pricecalc.mを追加

 

    アーカイブ情報:「BondTools」に変更
201866_204610.png

请转到“测试”选项卡,并按照以下设置。

    • ポート:デフォルトの9910のまま

 

    CORSを有効にする:チェックを入れる

当点击「启动」按钮时,服务会在 http://localhost:9910/BondTools 上开始监听。

201866_211949.png

确认动作

不需要搭建Web服务器,只需将先前的HTML / JavaScript文件放置在个人电脑的桌面上,并在浏览器中打开bptool.html。

image.png
201866_214852.png

但是,由于我正在使用原生的HTML/JavaScript来创建界面,所以界面看起来很简陋。我想要更加华丽的界面。

继续下半场。

我想要一个更加精致的网页前端。

既然要做,那就试着用框架来创建Material Design的界面吧,这是备忘录的后半部分。关于Angular的安装,可以参考Angular的快速入门指南或其他文章,从使用ng命令创建项目开始。

创建Angular项目

我們將專案命名為mpsBondCalc,然後使用ng new來建立專案。

使用`ng new mpsBondCalc`命令将创建一个包含各种Angular模板的项目。

安装Angular-Material

切换到项目的根文件夹,然后安装Angular-Material的全部组件。

cd mpsBondCalc
npm install –save @angular/material @angular/cdk
npm install –save @angular/animations
npm install –save hammerjs

根据Angular的入门教程中的第五步:手势支持,如果要使用滑块功能,则必须安装HammerJS,并在main.ts文件中添加import ‘hammerjs’。

在该模块中,使用Angular-Material导入了输入表单、滑块等控件(以Mat*为前缀)。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatCardModule, MatInputModule, MatSliderModule, MatDividerModule } from '@angular/material';    
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpModule } from '@angular/http';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    MatCardModule,
    MatInputModule,
    MatSliderModule,
    MatDividerModule,
    BrowserAnimationsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

将主要的app.component.html和app.component.ts文件进行移植,同时修改为适用于Angular的DOM操作,包括将示例中的bptool.html和calculatePrice.js进行移植。在bptool.html中使用了


作为分隔线,而在这里我们尝试使用Angular-Material的divider(mat-divider)。

<mat-card class="result">
    <mat-card-content>
        <h1><a>Bond Pricing Tool</a></h1>
        <h2></h2>
        This example shows an application that calculates a bond price from a simple formula.<p>
            You run this example by entering the following known values into a simple graphical interface:<p>
        <ul>
            <li>Face Value (or value of bond at maturity) - M</li>
            <li>Coupon payment - C</li>
            <li>Number of payments - N</li>
            <li>Interest rate - i</li>
        </ul>
        The application calculates price (P) based on the following equation:<p>
            P = C * ( (1 - (1 + i)^-N) / i ) + M * (1 + i)^-N<p>
        <mat-divider [inset]="true"></mat-divider>
        <h3>M: Face Value </h3>
        <form class="example-form form-inline" novalidate>
            <mat-form-field class="example-full-width">
                <input matInput type="number" name="facevalueValue" [(ngModel)]="facevalueValue"  min="0" max="10000" (change)="calculatePrice()">
            </mat-form-field>
            <mat-slider
                name="couponPaymentSlider"
                class="example-margin"
                [max]=10000
                [min]=0
                [(ngModel)]="facevalueValue"
                (change)="calculatePrice()">
            </mat-slider>
        </form>

        <h3>C: Coupon Payment </h3>
        <form class="example-form" novalidate>
            <mat-form-field class="example-full-width">
                <input matInput type="number" name="couponPaymentValue" [(ngModel)]="couponPaymentValue"  min="0" max="1000" (change)="calculatePrice()">
            </mat-form-field>
            <mat-slider
                name="couponPaymentSlider"
                class="example-margin"
                [max]=1000
                [min]=0
                [step]=0.01
                [(ngModel)]="couponPaymentValue"
                (change)="calculatePrice()">
            </mat-slider>            
        </form>

        <h3>N: Number of payments  </h3>
        <form class="example-form" novalidate>
            <mat-form-field class="example-full-width">
                <input matInput type="number" name="numPaymentsValue" [(ngModel)]="numPaymentsValue"  min="0" max="1000" (change)="calculatePrice()">
            </mat-form-field>
            <mat-slider
                name="numPaymentsSlider"
                class="example-margin"
                [max]=1000
                [min]=0
                [(ngModel)]="numPaymentsValue"
                (change)="calculatePrice()">
            </mat-slider>            
        </form>


        <h3>i: Interest rate </h3>      
        <form class="example-form" novalidate>
            <mat-form-field class="example-full-width ">
                <input matInput type="number" name="interestRateInput" [(ngModel)]="interestRateValue"  min="0" max="1" step="0.01" (change)="calculatePrice()">
            </mat-form-field>   
            <mat-slider
                name="interestRateSlider"
                id="interest_rate_slider"
                class="example-margin"
                [max]=1
                [min]=0
                [step]=0.01
                [(ngModel)]="interestRateValue"
                (change)="calculatePrice()">
            </mat-slider>            
        </form>

        <h2>BOND PRICE</h2>
        <p id="price_of_bond_value" style="font-weight: bold" #price_of_bond_value>
        <p id="error" style="color:red" #error>

        <mat-divider [inset]="true"></mat-divider>
        <h3>Request to MPS Server</h3>
        <p id="request" #request>

        <h3>Response from MPS Server</h3>
        <p id="response" #response>
        <mat-divider [inset]="true"></mat-divider>
    </mat-card-content>
</mat-card>
import {Component, ViewChild, ElementRef} from '@angular/core';
import {Http, Headers} from "@angular/http";
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})

export class AppComponent {
    @ViewChild('request') requestElement: ElementRef;
    @ViewChild('response') responseElement: ElementRef;
    @ViewChild('error') errorElement: ElementRef;
    @ViewChild('price_of_bond_value') priceOfBondValueElement: ElementRef;

    // Initial values
    facevalueValue = 0;
    couponPaymentValue = 0;
    numPaymentsValue = 0;
    interestRateValue = 0;

    httpOptions = {
        headers: new Headers({
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        })
    };

    constructor(private http: Http) {}

    // Calculate
    calculatePrice() {
        let url = "http://localhost:9910/BondTools/pricecalc";

        //Use MPS RESTful API to specify params using JSON
        let params = {
            "nargout": 1,
            "rhs": [this.facevalueValue, this.couponPaymentValue, this.interestRateValue, this.numPaymentsValue]
        };

        let requestElement = this.requestElement.nativeElement;
        requestElement.innerHTML = "URL: " + url + "<br>" + "Method: POST <br>" + "Data:" + JSON.stringify(params);


        const response = this.http.post(url, params, {headers: this.httpOptions.headers}).toPromise()
            .then(response => {
                //Use MPS RESTful API to check HTTP Status
                if (response.status === 200) {
                    // Deserialization: Converting text back into JSON object
                    // Response from server is deserialized 
                    let result = response.json();
                    //Use MPS RESTful API to retrieve response in "lhs"
                    if ('lhs' in result) {
                        let errorElement = this.errorElement.nativeElement;
                        errorElement.innerHTML = "";
                        let priceOfBondValueElement = this.priceOfBondValueElement.nativeElement;
                        priceOfBondValueElement.innerHTML = "Bond Price: " + result.lhs[0].mwdata;
                    } else {
                        let errorElement = this.errorElement.nativeElement;
                        errorElement.innerHTML = "Error: " + result.error.message;
                    }
                } else {
                    let errorElement = this.errorElement.nativeElement;
                    errorElement.innerHTML = "Error:" + response.statusText;
                }

                let responseElement = this.responseElement.nativeElement;
                responseElement.innerHTML = "Status: " + response.status + "<br>"
                    + "Status message: " + response.statusText + "<br>" +
                    "Response text: " + JSON.stringify(response.json());
        });
    }
}

我希望尽量减少修改,但使用ngModel在输入表单和滑块处非常方便实现,所以我进行了相当大的修改。

执行结果

现在我们来确认一下使用Angular-Material在Web前端的执行结果。
运行命令:ng serve –open。

201866_213411.png

不错不错,输入表单和滑动条变得现代化了,感觉不错。
在部署到 Web 服务器时,可以使用 ng build –prod 命令进行 TypeScript 编译,然后将生成的 HTML/JavaScript 文件放置在 Web 服务器上。而将 MATLAB Production Server 从 MATLAB 上的“模拟”转化为真正的打包好的 CTF 文件,并将其传递给 MATLAB Production Server 进行执行即可。但在开发 Web 前端时,方便调试的“模拟”方法会更加便利。

广告
将在 10 秒后关闭
bannerAds