From bffe5fc9990f7ecc464680d6fa4e5ccb7d58aded Mon Sep 17 00:00:00 2001
From: rex <rexkaneki@gmail.com>
Date: Thu, 6 May 2021 19:02:10 +0800
Subject: [PATCH] fix(radio): support set disabled dynamic (#4191)

---
 packages/radio-group/index.ts | 18 ++----------------
 packages/radio/index.ts       | 34 ++++++++++++++++++++++++++++++----
 packages/radio/index.wxml     | 13 +++++++------
 packages/radio/index.wxs      | 33 +++++++++++++++++++++++++++++++++
 4 files changed, 72 insertions(+), 26 deletions(-)
 create mode 100644 packages/radio/index.wxs

diff --git a/packages/radio-group/index.ts b/packages/radio-group/index.ts
index 6c290069..5ca8b544 100644
--- a/packages/radio-group/index.ts
+++ b/packages/radio-group/index.ts
@@ -4,9 +4,7 @@ import { useChildren } from '../common/relation';
 VantComponent({
   field: true,
 
-  relation: useChildren('radio', function (target) {
-    this.updateChild(target);
-  }),
+  relation: useChildren('radio'),
 
   props: {
     value: {
@@ -22,19 +20,7 @@ VantComponent({
 
   methods: {
     updateChildren() {
-      this.children.forEach(
-        (child: WechatMiniprogram.Component.TrivialInstance) =>
-          this.updateChild(child)
-      );
-    },
-
-    updateChild(child: WechatMiniprogram.Component.TrivialInstance) {
-      const { value, disabled, direction } = this.data;
-      child.setData({
-        value,
-        direction,
-        disabled: disabled || child.data.disabled,
-      });
+      this.children.forEach((child) => child.updateFromParent());
     },
   },
 });
diff --git a/packages/radio/index.ts b/packages/radio/index.ts
index 03fcae32..4f0ffc3e 100644
--- a/packages/radio/index.ts
+++ b/packages/radio/index.ts
@@ -1,10 +1,13 @@
+import { canIUseModel } from '../common/version';
 import { VantComponent } from '../common/component';
 import { useParent } from '../common/relation';
 
 VantComponent({
   field: true,
 
-  relation: useParent('radio-group'),
+  relation: useParent('radio-group', function () {
+    this.updateFromParent();
+  }),
 
   classes: ['icon-class', 'label-class'],
 
@@ -29,22 +32,45 @@ VantComponent({
     },
   },
 
+  data: {
+    direction: '',
+    parentDisabled: false,
+  },
+
   methods: {
+    updateFromParent() {
+      if (!this.parent) {
+        return;
+      }
+
+      const { value, disabled: parentDisabled, direction } = this.parent.data;
+
+      this.setData({
+        value,
+        direction,
+        parentDisabled,
+      });
+    },
+
     emitChange(value: boolean) {
       const instance = this.parent || this;
       instance.$emit('input', value);
       instance.$emit('change', value);
+
+      if (canIUseModel()) {
+        instance.setData({ value });
+      }
     },
 
     onChange() {
-      if (!this.data.disabled) {
+      if (!this.data.disabled && !this.data.parentDisabled) {
         this.emitChange(this.data.name);
       }
     },
 
     onClickLabel() {
-      const { disabled, labelDisabled, name } = this.data;
-      if (!disabled && !labelDisabled) {
+      const { disabled, parentDisabled, labelDisabled, name } = this.data;
+      if (!(disabled || parentDisabled) && !labelDisabled) {
         this.emitChange(name);
       }
     },
diff --git a/packages/radio/index.wxml b/packages/radio/index.wxml
index 4601c068..5f898c0b 100644
--- a/packages/radio/index.wxml
+++ b/packages/radio/index.wxml
@@ -1,27 +1,28 @@
 <wxs src="../wxs/utils.wxs" module="utils" />
+<wxs src="./index.wxs" module="computed" />
 
 <view class="{{ utils.bem('radio', [direction]) }} custom-class">
   <view
     wx:if="{{ labelPosition === 'left' }}"
-    class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled }]) }}"
+    class="{{ utils.bem('radio__label', [labelPosition, { disabled: disabled || parentDisabled }]) }} label-class"
     bindtap="onClickLabel"
   >
     <slot />
   </view>
-  <view class="van-radio__icon-wrap" style="font-size: {{ utils.addUnit(iconSize) }};" bindtap="onChange">
+  <view class="van-radio__icon-wrap" style="font-size: {{ utils.addUnit(iconSize) }}" bindtap="onChange">
     <slot wx:if="{{ useIconSlot }}" name="icon" />
     <van-icon
       wx:else
       name="success"
-      class="{{ utils.bem('radio__icon', [shape, { disabled, checked: value === name }]) }}"
-      style="font-size: {{ utils.addUnit(iconSize) }};{{ checkedColor && !disabled && value === name ? 'border-color:' + checkedColor + '; background-color:' + checkedColor + ';' : '' }}"
+      class="{{ utils.bem('radio__icon', [shape, { disabled: disabled || parentDisabled, checked: value === name }]) }}"
+      style="{{ computed.iconStyle({ iconSize, checkedColor, disabled, parentDisabled, value, name }) }}"
       custom-class="icon-class"
-      custom-style="line-height: {{ utils.addUnit(iconSize) }};font-size: .8em;display: block;"
+      custom-style="{{ computed.iconCustomStyle({ iconSize }) }}"
     />
   </view>
   <view
     wx:if="{{ labelPosition === 'right' }}"
-    class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled }]) }}"
+    class="label-class {{ utils.bem('radio__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
     bindtap="onClickLabel"
   >
     <slot />
diff --git a/packages/radio/index.wxs b/packages/radio/index.wxs
new file mode 100644
index 00000000..a428aad9
--- /dev/null
+++ b/packages/radio/index.wxs
@@ -0,0 +1,33 @@
+/* eslint-disable */
+var style = require('../wxs/style.wxs');
+var addUnit = require('../wxs/add-unit.wxs');
+
+function iconStyle(data) {
+  var styles = {
+    'font-size': addUnit(data.iconSize),
+  };
+
+  if (
+    data.checkedColor &&
+    !(data.disabled || data.parentDisabled) &&
+    data.value === data.name
+  ) {
+    styles['border-color'] = data.checkedColor;
+    styles['background-color'] = data.checkedColor;
+  }
+
+  return style(styles);
+}
+
+function iconCustomStyle(data) {
+  return style({
+    'line-height': addUnit(data.iconSize),
+    'font-size': '.8em',
+    display: 'block',
+  });
+}
+
+module.exports = {
+  iconStyle: iconStyle,
+  iconCustomStyle: iconCustomStyle,
+};