NPM package [bitcoinjs-lib] not compatible with IE v11 - internet-explorer-11

I'm adding IE v11 support for web application. bitcoinjs-lib package contains arrow function causing IE v11 to break.
I have added babel-polyfill, react-app-polyfill/ie11, url-search-params-polyfill and react-app-polyfill/stable which makes up for most IE v11 support expect bitcoinjs-lib package.
Image in IE v11 browser
.bashrc
{
"plugins": [
["#babel/plugin-transform-arrow-functions"],
[
"module-resolver", {
"root": ["./"],
"alias": {
"~": "./"
}
}]
],
"presets": [
[
"next/babel",
{
"preset-env": {
"useBuiltIns": "usage"
}
}
]
]
}
source code inside package
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const parser_1 = require('../parser');
function combine(psbts) {
const self = psbts[0];
const selfKeyVals = parser_1.psbtToKeyVals(self);
const others = psbts.slice(1);
if (others.length === 0) throw new Error('Combine: Nothing to combine');
const selfTx = getTx(self);
if (selfTx === undefined) {
throw new Error('Combine: Self missing transaction');
}
const selfGlobalSet = getKeySet(selfKeyVals.globalKeyVals);
const selfInputSets = selfKeyVals.inputKeyVals.map(input => getKeySet(input));
const selfOutputSets = selfKeyVals.outputKeyVals.map(output =>
getKeySet(output),
);
for (const other of others) {
const otherTx = getTx(other);
if (
otherTx === undefined ||
!otherTx.toBuffer().equals(selfTx.toBuffer())
) {
throw new Error(
'Combine: One of the Psbts does not have the same transaction.',
);
}
const otherKeyVals = parser_1.psbtToKeyVals(other);
const otherGlobalSet = getKeySet(otherKeyVals.globalKeyVals);
otherGlobalSet.forEach(
keyPusher(
selfGlobalSet,
selfKeyVals.globalKeyVals,
otherKeyVals.globalKeyVals,
),
);
const otherInputSets = otherKeyVals.inputKeyVals.map(input =>
getKeySet(input),
);
otherInputSets.forEach((inputSet, idx) =>
inputSet.forEach(
keyPusher(
selfInputSets[idx],
selfKeyVals.inputKeyVals[idx],
otherKeyVals.inputKeyVals[idx],
),
),
);
const otherOutputSets = otherKeyVals.outputKeyVals.map(output =>
getKeySet(output),
);
otherOutputSets.forEach((outputSet, idx) =>
outputSet.forEach(
keyPusher(
selfOutputSets[idx],
selfKeyVals.outputKeyVals[idx],
otherKeyVals.outputKeyVals[idx],
),
),
);
}
return parser_1.psbtFromKeyVals(selfTx, {
globalMapKeyVals: selfKeyVals.globalKeyVals,
inputKeyVals: selfKeyVals.inputKeyVals,
outputKeyVals: selfKeyVals.outputKeyVals,
});
}
exports.combine = combine;
function keyPusher(selfSet, selfKeyVals, otherKeyVals) {
return key => {
if (selfSet.has(key)) return;
const newKv = otherKeyVals.filter(kv => kv.key.toString('hex') === key)[0];
selfKeyVals.push(newKv);
selfSet.add(key);
};
}
function getTx(psbt) {
return psbt.globalMap.unsignedTx;
}
function getKeySet(keyVals) {
const set = new Set();
keyVals.forEach(keyVal => {
const hex = keyVal.key.toString('hex');
if (set.has(hex))
throw new Error('Combine: KeyValue Map keys should be unique');
set.add(hex);
});
return set;
}
.next.config.js
const fs = require('fs')
const dotenv = require('dotenv')
const webpack = require('webpack')
const withCSS = require('#zeit/next-css')
const withFonts = require('next-fonts')
const withImages = require('next-images')
const withPlugins = require("next-compose-plugins")
const withTM = require('next-transpile-modules');
const getEnvFile = () => {
const fileName = process.env.NODE_ENV == 'development' ? '.env' : `.env.${process.env.NODE_ENV}`
return fs.readFileSync(fileName)
}
const envConfig = dotenv.parse(getEnvFile())
const nextConfig = {
webpack(config) {
config.plugins.push(new webpack.EnvironmentPlugin(envConfig))
const originalEntry = config.entry;
config.entry = async () => {
const entries = await originalEntry();
if (entries['main.js'] && !entries['main.js'].includes('./polyfills.js')) {
entries['main.js'].unshift('./polyfills.js');
}
return entries;
};
config.module.rules.push({
test: /\.js$/,
include: [/node_modules\/bitcoinjs-lib/],
use: {
loader: "next/babel",
options: {
presets: ["#babel/presets-env", {modules: false}],
plugins: ["#babel/plugin-transform-arrow-functions"],
},
},
})
return config
},
exportPathMap: async function(defaultPathMap) {
return {
'/' : { page: '/people' },
'/dashboard' : { page: '/dashboard' },
'/tenant-investigator' : { page: '/tenant_investigator' },
'/pricing-history' : { page: '/pricingHistory' },
'/algorithm' : { page: '/algorithm' },
'/group' : { page: '/group' },
'/group-detail' : { page: '/group_detail' },
'/investigation' : { page: '/investigation' },
'/login' : { page: '/login' },
'/map' : { page: '/map' },
'/people' : { page: '/people' },
'/people-report' : { page: '/people_report' },
'/report' : { page: '/report' },
'/people-detail' : { page: '/people_detail' },
'/pricing-history' : { page: '/pricingHistory' },
'/settings' : { page: '/settings' },
'/tenant' : { page: '/tenant' },
'/wallets' : { page: '/wallets' },
'/transactions' : { page: '/transactions' },
'/taxable-event' : { page: '/taxable_event' },
'/subpoena-upload' : { page: '/subpoenaUpload' },
'/people-subpoena-upload': { page: '/peopleSubpoenaUpload' },
'/subpoena-transactions' : { page: '/subpoenaTransactions' },
'/event-detail' : { page: '/peopleEvent' },
'/grand-unified' : { page: '/grandUnified' },
'/blocks' : { page: '/blocks' },
'/person-edit' : { page: '/personEdit' },
'/addresses' : { page: '/addresses' },
'/exchanges' : { page: '/exchanges' }
}
}
}
console.log(nextConfig)
// module.exports = withPlugins([withCSS, withFonts, withImages], nextConfig)
module.exports = withPlugins(
[
[
withTM,
{
transpileModules: ['bitcoinjs-lib']
}
],
withCSS,
withFonts,
withImages
],
nextConfig
);
As we see use of arrow function causing error
I want node_module package to be converted to native javascript to IE v11 can read easily. When I look in to node_module source, arrow function and ES6 can be seen in package shipment.

Related

sequelize findandcountall function return same data when using pagination

I am using sequelize: 6.9.0, sequelize-cli: ^6.3.0, express: 4.17.1, pg: 8.7.1
i have a problem when using sequelize findAndCountAll, when i using include other models it will return same data when i'm using paging.
Here is my code for House Table
index: async (req, res) => {
const { page, size, developer, city, priceone, pricetwo, project, isNew } =
req.query;
const { limit, offset } = getPagination(page, size);
try {
let filter = {};
if (developer) {
filter.developerId = developer;
}
if (city) {
filter.cityId = city;
}
if (project) {
filter.projectId = project;
}
if (isNew) {
filter.isNew = isNew;
}
if (priceone && pricetwo) {
const firstPrice = parseInt(priceone);
const secondPrice = parseInt(pricetwo);
if (firstPrice === 100000000 && secondPrice === 100000000) {
filter.price = { [Op.lte]: firstPrice };
} else if (firstPrice === 2000000000 && secondPrice === 2000000000) {
filter.price = { [Op.gte]: firstPrice };
} else {
filter.price = { [Op.between]: [firstPrice, secondPrice] };
}
}
const HousesData = await Houses.findAndCountAll({
limit,
offset,
where: filter,
attributes: [
"id",
"name",
"description",
"location",
"price",
"tanah",
"bangunan",
"lantai",
"kamar_tidur",
"kamar_mandi",
"isNew",
],
include: [
{ model: Developers, attributes: ["id", "name"] },
{ model: Cities, attributes: ["id", "name"] },
{ model: Projects, attributes: ["id", "name"] },
],
});
if (HousesData) {
const response = getPagingData(HousesData, page, limit);
res.status(200).json({
status: "success",
message: "Data Available",
data: response,
});
} else {
res.status(200).json({
status: "success",
message: "There is No Data",
data: "No Data",
});
}
} catch (error) {
console.log(error);
return next(
new HttpError(
"Something went wrong, could not get project.",
500,
error
)
);
}
}
my paging function
const getPagination = (page, size) => {
const newPage = page ? page - 1 : 0;
const limit = size ? +size : 10;
const offset = newPage != 0 ? newPage * limit : 0;
return { limit, offset };
};
const getPagingData = (data, page, limit) => {
const { count: totalItems, rows: dataRows } = data;
const currentPage = page ? +page : 1;
const totalPages = Math.ceil(totalItems / limit);
return { totalItems, totalPages, currentPage, dataRows };
};
module.exports = { getPagination, getPagingData };
Let's say i have 10 data
a,b,c,d,e,f,g,h,i,j
if i see first page
http://localhost:3006/api/v1/house?size=5&page=1
it will return a,b,c,d,e (this is right)
and if i see next page
http://localhost:3006/api/v1/house?size=5&page=2
it will return e,d,c,b,a (only reverse not showing f,g,h,i,j)
and if i see all the data it will return correct data
http://localhost:3006/api/v1/house?size=10&page=1
it will return j,i,h,g,f,e,d,c,b,a
but if i disabled
include: [
{ model: Developers, attributes: ["id", "name"] },
{ model: Cities, attributes: ["id", "name"] },
{ model: Projects, attributes: ["id", "name"] },
],
it return the right data when use paging.
my model for House is here
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("Houses", {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.STRING(22),
},
name: {
type: Sequelize.STRING,
},
projectId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Projects",
key: "id",
},
},
cityId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Cities",
key: "id",
},
},
developerId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Developers",
key: "id",
},
},
description: {
type: Sequelize.TEXT,
},
location: {
type: Sequelize.STRING,
},
price: {
type: Sequelize.BIGINT,
},
tanah: {
type: Sequelize.INTEGER,
},
bangunan: {
type: Sequelize.INTEGER,
},
lantai: {
type: Sequelize.INTEGER,
},
kamar_tidur: {
type: Sequelize.INTEGER,
},
kamar_mandi: {
type: Sequelize.INTEGER,
},
house_thumbnail: {
type: Sequelize.STRING,
},
isNew: {
type: Sequelize.BOOLEAN,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Houses");
},
};
i also use same paging method on other table. but other table works fine, only this table that got messed up.
the other table named Project function is here for reference
index: async (req, res) => {
const { page, size, developer, city, priceone, pricetwo } = req.query;
const { limit, offset } = getPagination(page, size);
try {
let filter = { haveDeveloper: true };
if (developer) {
filter.developerId = developer;
}
if (city) {
filter.cityId = city;
}
if (priceone && pricetwo) {
const firstPrice = parseInt(priceone);
const secondPrice = parseInt(pricetwo);
if (firstPrice === 100000000 && secondPrice === 100000000) {
filter.minPrice = { [Op.lte]: firstPrice };
} else if (firstPrice === 2000000000 && secondPrice === 2000000000) {
filter.minPrice = { [Op.gte]: firstPrice };
} else {
filter.minPrice = { [Op.between]: [firstPrice, secondPrice] };
}
}
const projectsData = await Projects.findAndCountAll({
limit,
offset,
where: filter,
attributes: ["id", "name", "image", "location",'minPrice'],
include: [
{ model: Cities, attributes: ["id", "name"] },
{ model: Developers, attributes: ["id", "name"] },
{ model: ProjectFacilities, attributes: ["facility"] },
],
});
if (projectsData) {
const response = getPagingData(projectsData, page, limit);
res.status(200).json({
status: "success",
message: "Data Available",
data: response,
});
} else {
res.status(200).json({
status: "success",
message: "There is No Data",
data: "No Data",
});
}
} catch (error) {
console.log(error);
return next(
new HttpError(
"Something went wrong, could not get project.",
500,
error
)
);
}
},
the Project model
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Projects extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
Projects.belongsTo(models.Developers, { foreignKey: 'developerId' })
Projects.belongsTo(models.Cities, { foreignKey: 'cityId' })
Projects.hasMany(models.ProjectFacilities, { foreignKey: 'projectId' })
Projects.hasMany(models.Houses, { foreignKey: 'projectId' })
}
};
Projects.init({
name: DataTypes.STRING,
image: DataTypes.STRING,
description: DataTypes.TEXT,
location: DataTypes.STRING,
minPrice:DataTypes.BIGINT,
haveDeveloper: DataTypes.BOOLEAN,
cityId: DataTypes.STRING,
developerId: DataTypes.INTEGER
}, {
sequelize,
modelName: 'Projects',
});
return Projects;
};
sql generated by sequelize for House page 1 with 5 data
SELECT "Houses"."id", "Houses"."name", "Houses"."description", "Houses"."location", "Houses"."price", "Houses"."tanah", "Houses"."bangunan", "Houses"."lantai", "Houses"."kamar_tidur", "Houses"."kamar_mandi", "Houses"."isNew", "Developer"."id" AS "Developer.id", "Developer"."name" AS "Developer.name", "City"."id" AS "City.id", "City"."name" AS "City.name", "Project"."id" AS "Project.id", "Project"."name" AS "Project.name" FROM "Houses" AS "Houses" LEFT OUTER JOIN "Developers" AS "Developer" ON "Houses"."developerId" = "Developer"."id" LEFT OUTER JOIN "Cities" AS "City" ON "Houses"."cityId" = "City"."id" LEFT OUTER JOIN "Projects" AS "Project" ON "Houses"."projectId" = "Project"."id" LIMIT 5 OFFSET 0;
sql generated by sequelize for Project page 1 with 5 data
SELECT "Projects".*, "City"."id" AS "City.id", "City"."name" AS "City.name", "Developer"."id" AS "Developer.id", "Developer"."name" AS "Developer.name", "ProjectFacilities"."id" AS "ProjectFacilities.id", "ProjectFacilities"."facility" AS "ProjectFacilities.facility" FROM (SELECT "Projects"."id", "Projects"."name", "Projects"."image", "Projects"."location", "Projects"."minPrice", "Projects"."cityId", "Projects"."developerId" FROM "Projects" AS "Projects" WHERE "Projects"."haveDeveloper" = true LIMIT 5 OFFSET 0) AS "Projects" LEFT OUTER JOIN "Cities" AS "City" ON "Projects"."cityId" = "City"."id" LEFT OUTER JOIN "Developers" AS "Developer" ON "Projects"."developerId" = "Developer"."id" LEFT OUTER JOIN "ProjectFacilities" AS "ProjectFacilities" ON "Projects"."id" = "ProjectFacilities"."projectId";
is there any solution for this? thank you very much for your all help and attention!
Please try thi
const getPagination = (page = 1, size = 10) => {
const offset = (page - 1) * size ;
const limit = size ;
return { limit, offset };
};

Ant Design Vue | Upload in Form | How to set initialValue

I'm having problems defining the initialValue in an Upload component, other thing I tried was using a watcher and updating the formValue and the method that update the props FileList. ¿Someone has any idea how this work?
Parent.vue
<Child :file="file"/>
...
async loadFile(item) {
this.loading = true
const { data } = await axios(..., {
...
responseType: 'blob',
})
const file = new File([data], item.name, { type: data.type });
this.file= {
Id: item.id,
Type: item.attributes.type,
IsPublic: item.attributes.is_public,
Descr: item.attributes.descr,
File: [file]
}
this.showForm();
this.loading = false
},
Children.vue
<a-upload
:accept="formats"
:before-upload="beforeUploadEvt"
:disabled="!formats"
:remove="removeFileEvt"
v-decorator="[
'File',
{
valuePropName: 'fileList',
getValueFromEvent: getValueEvt,
rules: [{ required: true, message: 'Select a file' }]
},
]" >
<a-button> <a-icon type="upload" /> Select a file</a-button>
</a-upload>
methods: {
beforeUploadEvt(file) {
this.form.setFieldsValue({
File: [file]
});
return false;
},
removeFileEvt() {
this.formulario.setFieldsValue({
Archivo: []
});
},
getValueEvt(e) {
if (Array.isArray(e)) {
return e;
}
if(e && e.fileList.length > 1) {
return e && [e.fileList[1]];
}
return e && e.fileList;
},
},
watch: {
adjunto: {
immediate: true,
deep: true,
handler(obj) {
if(obj.File) {
this.getValueEvt(obj.File);
// this.formulario.setFieldsValue({
// File: obj.File
// });
}
}
}
}
Trying the most basic example I could think, using the property defaultFileList
<a-upload
:accept="formats"
:before-upload="beforeUploadEvt"
:disabled="!format"
:remove="removeFileEvt"
:default-file-list="this.file.File">
<a-button> <a-icon type="upload" /> Select file</a-button>
</a-upload>
And then, this is the console warnings and errors I got, so seems to be something about type.
If anyone still seeking for an answer for this. You don't need to load file, wrapping your data in appropriate object helps. As in this example
fileList: [{
uid: '-1',
name: 'image.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
}]
<a-upload
....
:file-list="fileList"
>

I'm getting the error in vue.js - Unexpected side effect in "filteredTeamsData" computed property

Unexpected side effect in "filteredTeamsData" computed property
I have imported the two JSON file
import seasonList from '../assets/data/season_list.json'
import team data from '../assets/data/match_team.json'
Code -
export default {
name: 'SeasonSplit',
components: {
TableElement,
},
data () {
return {
selected: '1',
teamData: teamData,
teamList: [],
seasonList: seasonList,
filteredData: [],
tableColumns: ['toss_wins', 'matches', 'wins', 'losses', 'pts']
}
},
computed: {
filteredTeamsData: function () {
this.dataArr = []
this.filteredData = []
this.teamList = []
teamData.forEach(element => {
if(element.season == seasonList[this.selected-1]){
this.filteredData.push(element)
this.teamList.push(element.team)
this.dataArr.push(element.wins)
}
})
// console.log(this.filteredData)
return this.dataArr
}
}
}
I'd do it as follows:
export default {
name: 'SeasonSplit',
components: {
TableElement,
},
data () {
let filteredData = [];
let teamList = [];
let dataArr = [];
teamData.forEach(element => {
if(element.season == seasonList[this.selected-1]){
filteredData.push(element)
teamList.push(element.team)
dataArr.push(element.wins)
}
});
return {
selected: '1',
teamData: teamData,
teamList: teamList ,
seasonList: seasonList,
filteredData: filteredData ,
tableColumns: ['toss_wins', 'matches', 'wins', 'losses', 'pts'],
filteredTeamsData: dataArr
}
}

Load CSS from a dynamically imported ES6 module

My project is being built with Webpack via Laravel Mix. I want to dynamically import an ES6 module that itself imports other modules and a stylesheet. Here is the dynamically imported module (loadJQueryTextillate.js):
import style from 'animate.css/animate.css';
import 'letteringjs';
import 'textillate';
style.use();
export default () => {
};
Here is the module that dynamically imports loadJQueryTextillate.js (animatedText.js):
import isInViewport from './isInViewport';
function maybeAnimateText( elem ) {
const $el = $( elem );
let bounding,
el_html,
el_lines,
in_viewport = $el.data( 'in-viewport' ) || false;
const viewport_height = window.innerHeight || document.documentElement.clientHeight;
if ( $el.hasClass( 'opaque' ) ) {
bounding = elem.getBoundingClientRect();
if ( in_viewport && !isInViewport( elem ) && ( bounding.top > viewport_height ) ) { // Element scrolled off screen
in_viewport = false;
$el.removeClass( 'opaque' ).find( 'ul.texts' ).remove().end().text( $.trim( $el.text() ) );
} else if ( isInViewport( elem ) ) {
in_viewport = true;
}
$el.data( 'in-viewport', in_viewport );
return;
} else if ( !isInViewport( elem ) ) {
return;
}
el_html = $el.html();
el_lines = el_html.split( /<br\s*\/?>/ );
$.each( el_lines, function( key, line ) {
el_lines[ key ] = $.trim( line );
} );
el_html = '<span class="line">' + el_lines.join( '</span><span class="line">' ) + '</span>';
import( /* webpackChunkName: "scripts/jQuery.textillate" */ './loadJQueryTextillate' ).then( () => {
$el.html( el_html ).addClass( 'opaque' ).children( '.line' ).textillate( {
in : {
effect : $el.data( 'in-effect' ) || 'fadeInLeft',
delay : $el.data( 'delay' ) || 12,
},
} );
} );
}
export default () => {
const $els = $( '.tlt' );
if ( 0 === $els.length ) {
return false;
}
$els.each( function( index, elem ) {
maybeAnimateText( elem );
} );
return true;
};
Here is the JS entry script (app.js):
window.$ = window.jQuery = require( 'jquery' );
import 'bootstrap';
import checkAnimatedText from './modules/animatedText';
$( window ).on( 'load', () => {
checkAnimatedText();
} );
Finally, here is the Laravel Mix config script (webpack.mix.js):
const mix = require( 'laravel-mix' );
require( 'laravel-mix-versionhash' );
// Public path helper
const publicPath = path => `${mix.config.publicPath}/${path}`;
// Source path helper
const src = path => `resources/assets/${path}`;
// Public Path
mix
.setPublicPath( './dist' )
.setResourceRoot( `/wp-content/themes/magnetar/${mix.config.publicPath}/` )
.webpackConfig( {
module : {
rules : [ {
test : /animate\.css$/,
use : [ {
loader : "style-loader/useable",
}, { loader : "css-loader" } ],
} ],
},
output : { publicPath : mix.config.resourceRoot },
} );
// Browsersync
mix.browserSync( 'magnetar.localhost' );
// Styles
mix.sass( src`styles/app.scss`, 'styles' );
// Assets
mix.copyDirectory( src`images`, publicPath`images` )
.copyDirectory( src`fonts`, publicPath`fonts` );
// JavaScript
mix.js( src`scripts/app.js`, 'scripts' );
//.extract();
// Autoload
/*mix.autoload( {
jquery : [ '$', 'window.jQuery' ],
} );*/
// Source maps when not in production.
mix.sourceMaps( false, 'source-map' );
// Hash and version files in production.
mix.versionHash( { length : 16 } );
Compiler output:
ERROR in ./node_modules/animate.css/animate.css (./node_modules/css-loader??ref--6-1!./node_modules/postcss-loader/src??ref--6-2!./node_modules/style-loader/useable.js!./node_modules/css-loader!./node_modules/animate.css/animate.css)
Module build failed (from ./node_modules/postcss-loader/src/index.js):
SyntaxError
(1:1) Unknown word
> 1 | var refs = 0;
| ^
2 | var dispose;
3 | var content = require("!!../css-loader/index.js!./animate.css");
EDIT: Updated contents of loadJQueryTextillate.js, webpack.mix.js and compiler output.
You can try style-loader/useable to dynamically load css file. In your script code, you should use style.use() to make style useable or use style.unuse() to make style disable.
The following code shows how you should do to use style-loader/useable.
webpack.config.js
{
module: {
rules: [
{
test: /\.css$/,
exclude: /\.useable\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
],
},
{
test: /\.useable\.css$/,
use: [
{
loader: "style-loader/useable"
},
{ loader: "css-loader" },
],
},
],
},
}
file you want to dynamically load animate.css
import style form './animate.css';
// make aniamte.css useable
style.use();
// make animate.css disable
style.unuse();

Trouble getting m.request to auto-cast to a class in Mithril

I have defined a class and am asking m.request to cast a web service's JSON response to it, but each of the class properties come out equal to n/b(), and my view renders each property as function (){return arguments.length&&(a=arguments[0]),a}.
If I do not attempt to auto-cast the JSON response to my class in m.request, then my view renders just fine, which I think tells me that the JSON object returned by the web service is valid JSON.
I want to use my class. What is wrong?
Here is an edited sample of the JSON returned by the web service:
{
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"blah blah",
"indent":"true",
"wt":"json"}
},
"response":{
"numFound":97,
"start":0,
"docs":[
{
"identifier":"abc123",
"heading":"A Great Heading",
"id":"abc-123-1",
"title":"A Title",
"url":"path/to/some.html",
"content":["Blah blah blah blah blee blah."]
},
{
"identifier":"xyz789",
"heading":"Another Heading",
"id":"xyz-789-1",
"title":"Another Title",
"url":"another/path/to.html",
"content":["My bonny lies over the ocean."]
}
]
}
}
Here is my Mithril app:
var findus = {};
findus.Document = function (data) {
this.id = m.prop(data.id);
this.title = m.prop(data.title);
this.heading = m.prop(data.heading);
this.identifier = m.prop(data.identifer);
this.url = m.prop("//" + data.url + "#" + data.identifier);
};
findus.vm = (function() {
var vm = {};
vm.init = function () {
// user input
vm.queryText = m.prop("");
vm.search = function () {
if (vm.queryText()) {
vm.results = m.request({
method: "GET",
url: "/prd/query?q=" + vm.queryText(),
type: findus.Document,
unwrapSuccess: function (response) {
return response.response.docs;
},
unwrapError: function (response) {
console.log(response);
}
}).bind(vm);
}
};
};
return vm;
}());
findus.controller = function () {
findus.vm.init();
};
findus.view = function () {
return [
m("input", {onchange: m.withAttr("value", findus.vm.queryText), value: findus.vm.queryText()}),
m("button", {onclick: findus.vm.search}, "Search"),
findus.vm.results ? m("div", [
findus.vm.results().map(function (result) {
return m("div", [
m("h2", result.heading),
m("p", result.content),
m("a", {href: result.url}, result.url)
]);
})
]) : ""
];
};
m.module(document.body, {controller: findus.controller, view: findus.view});
Oh, bugger. I forgot that my class properties are getter/setters via m.prop, so I should have been calling them as functions in the view -- see below.
False alarm, problem solved, I'm embarrassed.
findus.view = function () {
return [
m("input", {onchange: m.withAttr("value", findus.vm.queryText), value: findus.vm.queryText()}),
m("button", {onclick: findus.vm.search}, "Search"),
findus.vm.results ? m("div", [
findus.vm.results().map(function (result) {
return m("div", [
m("h2", result.heading()),
m("p", m.trust(result.content())),
m("a", {href: result.url()}, result.url())
]);
})
]) : ""
];
};