From e1a338eed47706aac506893bf87f56b452a7b139 Mon Sep 17 00:00:00 2001 From: Alex Simonides Date: Thu, 26 Aug 2021 15:38:05 -0700 Subject: [PATCH] Fix partial-numeric string prop parsing Internally Vue was using `parseFloat` for this, and `parseFloat('1abc') === 1` rather than `NaN` like it is for non-numeric strings The fix was lifted from https://github.com/vuejs/vue-next/pull/4393, so I'll double check whether that's been merged by the time the rest of this is ready --- demo-app/_vue-components/index.js | 2 + demo-app/_vue-components/prop-tester.vue | 64 ++++++++++++++++++++++++ demo-app/_vue-components/user-list.vue | 42 +++++++++------- demo-app/home/home.controller.js | 21 ++++++-- demo-app/home/home.html | 13 ++++- demo-app/style.css | 15 ++++-- lib/vue-wrapper/index.js | 16 ++++++ 7 files changed, 145 insertions(+), 28 deletions(-) create mode 100644 demo-app/_vue-components/prop-tester.vue diff --git a/demo-app/_vue-components/index.js b/demo-app/_vue-components/index.js index 8817f75..367e601 100644 --- a/demo-app/_vue-components/index.js +++ b/demo-app/_vue-components/index.js @@ -1,10 +1,12 @@ import { defineNatively } from '@blueshift/ng-interop'; +import PropTester from './prop-tester.vue'; import UserItem from './user-item.vue'; import UserList from './user-list.vue'; defineNatively([ + PropTester, UserItem, UserList, ]); diff --git a/demo-app/_vue-components/prop-tester.vue b/demo-app/_vue-components/prop-tester.vue new file mode 100644 index 0000000..9db812f --- /dev/null +++ b/demo-app/_vue-components/prop-tester.vue @@ -0,0 +1,64 @@ + + + + + \ No newline at end of file diff --git a/demo-app/_vue-components/user-list.vue b/demo-app/_vue-components/user-list.vue index 0aed3c5..1c39981 100644 --- a/demo-app/_vue-components/user-list.vue +++ b/demo-app/_vue-components/user-list.vue @@ -1,28 +1,34 @@ diff --git a/demo-app/home/home.controller.js b/demo-app/home/home.controller.js index f50534d..a1e171a 100644 --- a/demo-app/home/home.controller.js +++ b/demo-app/home/home.controller.js @@ -4,11 +4,26 @@ class HomeCtrl { 'UserService', ]; + name = 'AngularJS inside ng-wrapper vue component'; + users = []; + selectedId = null; + testProps = { + title: '1string', + likes: 4, + is_published: true, + comment_ids: ['a1', '2b', 'c3'], + author: { + name: 'Alex', + published: true, + post_count: 10, + }, + callback: function testCb() {}, + promise: Promise.resolve(10), + }; + + constructor($scope, UserService) { - this.name = 'AngularJS'; this.UserService = UserService; - this.users = []; - this.selectedId = null; this.$scope = $scope; } diff --git a/demo-app/home/home.html b/demo-app/home/home.html index fb61905..2fe3dcf 100644 --- a/demo-app/home/home.html +++ b/demo-app/home/home.html @@ -7,7 +7,7 @@

Hello {{ $ctrl.name }}!

-

+

AngularJS (control)

+
diff --git a/demo-app/style.css b/demo-app/style.css index b9483e8..e1e1a9d 100644 --- a/demo-app/style.css +++ b/demo-app/style.css @@ -1,11 +1,7 @@ :root { --c-ng1: #B52E31; --c-vue: #42b983; -} - -h1, -p { - font-family: Lato; + font-family: 'Helvetica Neue', Arial, sans-serif; } #app { @@ -13,11 +9,20 @@ p { max-width: 100vw; margin: 0 auto; } +h2 { + margin-top: 0; +} .list-container { display: grid; width: 100%; grid-template-columns: repeat(2, 1fr); + gap: 1rem; +} + +.vue-heading { + border-left: 4px solid var(--c-vue); + padding-left: 8px; } .user { diff --git a/lib/vue-wrapper/index.js b/lib/vue-wrapper/index.js index fcc653f..5dce607 100644 --- a/lib/vue-wrapper/index.js +++ b/lib/vue-wrapper/index.js @@ -378,6 +378,10 @@ export function defineGuardedCustomElement(options) { }) } + _setAttr(key) { + this._setProp(camelize(key), parseNumber(this.getAttribute(key)), false); + } + _setProp(key, val, shouldReflect = true) { if (key?.startsWith('ng')) { // Skip any attributes that start with `ng-` @@ -479,3 +483,15 @@ export function defineGuardedCustomElement(options) { return customElementClass; } + +/** + * @TODO: this can just be imported from the library once https://github.com/vuejs/vue-next/pull/4393 is merged + * @param {string|null} value + * @return {string|number} + */ +export function parseNumber(value) { + // for Number('') and Number(null) as they both become 0 + if (!value) return ''; + const casted = Number(value); + return value === 'NaN' || !Number.isNaN(casted) ? casted : value; +}