From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <d.csapak@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id EE3A277E2E
 for <pve-devel@lists.proxmox.com>; Mon, 25 Oct 2021 11:32:16 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id E0617210D6
 for <pve-devel@lists.proxmox.com>; Mon, 25 Oct 2021 11:31:46 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS id 8927F210CB
 for <pve-devel@lists.proxmox.com>; Mon, 25 Oct 2021 11:31:45 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 57E3345ED0
 for <pve-devel@lists.proxmox.com>; Mon, 25 Oct 2021 11:31:45 +0200 (CEST)
From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Mon, 25 Oct 2021 11:31:44 +0200
Message-Id: <20211025093144.2644693-1-d.csapak@proxmox.com>
X-Mailer: git-send-email 2.30.2
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.278 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pve-devel] [PATCH widget-toolkit v2] cbind: document cbind by
 adding a small summary and example
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Mon, 25 Oct 2021 09:32:17 -0000

Explain the use-case, the difference to normal binds, and give an
example that contains all features that can be used with explanations.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v1:
* rewrite of textual introduction to include more details about use
* remove part about double-bind, should be clear from the 'applied
  once' bit.
* remove comments in the example in favor of textual explanation at the
  beginning
* add info about recursion and workaround (+example)

 src/mixin/CBind.js | 96 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/src/mixin/CBind.js b/src/mixin/CBind.js
index 8b4153c..8cd5bb3 100644
--- a/src/mixin/CBind.js
+++ b/src/mixin/CBind.js
@@ -1,3 +1,99 @@
+/*
+ * The Proxmox CBind mixin is intended to supplement the 'bind' mechanism
+ * of ExtJS. In contrast to the 'bind', 'cbind' only acts during the creation
+ * of the component, not during its lifetime. It's only applied once before
+ * the 'initComponent' method is executed, and thus you have only access
+ * to the basic initial configuration of it.
+ *
+ * You can use it to get a 'declarative' approach to component declaration,
+ * even when you need to set some properties of sub-components dynamically
+ * (e.g., the 'nodename'). It overwrites the given properties of the 'cbind'
+ * object in the component with their computed values of the computed
+ * cbind configuration object of the 'cbindData' function (or object).
+ *
+ * The cbind syntax is inspired by ExtJS' bind syntax ('{property}'), where
+ * it is possible to negate values ('{!negated}'), access sub-properties of
+ * objects ('{object.property}') and even use a getter function,
+ * akin to viewModel formulas ('(get) => get("prop")') to execute more
+ * complicated dependencies (e.g., urls).
+ *
+ * The 'cbind' will be recursively applied to all properties (objects/arrays)
+ * that contain an 'xtype' or 'cbind' property, but stops for a subtree if the
+ * object in question does not have either (if you have one or more levels that
+ * have no cbind/xtype property, you can insert empty cbind objects there to
+ * reach deeper nested objects).
+ *
+ * This reduces the code in the 'initComponent' and instead we can statically
+ * declare items, buttons, tbars, etc. while the dynamic parts are contained
+ * in the 'cbind'.
+ *
+ * It is used like in the following example:
+ *
+ * Ext.define('Some.Component', {
+ *     extend: 'Some.other.Component',
+ *
+ *     // first it has to be enabled
+ *     mixins: ['Proxmox.Mixin.CBind'],
+ *
+ *     // then a base config has to be defined. this can be a function,
+ *     // which has access to the initial config and can store persistent
+ *     // properties, as well as return temporary ones (which only exist during
+ *     // the cbind process)
+ *     // this function will be called before 'initComponent'
+ *     cbindData: function(initialconfig) {
+ *         // 'this' here is the same as in 'initComponent'
+ *         let me = this;
+ *         me.persistentProperty = false;
+ *         return {
+ *             temporaryProperty: true,
+ *         };
+ *     },
+ *
+ *     // if there is no need for persistent properties, it can also simply be an object
+ *     cbindData: {
+ *         temporaryProperty: true,
+ *         // properties itself can also be functions that will be evaluated before
+ *         // replacing the values
+ *         dynamicProperty: (cfg) => !cfg.temporaryProperty,
+ *         numericProp: 0,
+ *         objectProp: {
+ *             foo: 'bar',
+ *             bar: 'baz',
+ *         }
+ *     },
+ *
+ *     // you can 'cbind' the component itself, here the 'target' property
+ *     // will be replaced with the content of 'temporaryProperty' (true)
+ *     // before the components initComponent
+ *     cbind: {
+ *          target: '{temporaryProperty}',
+ *     },
+ *
+ *     items: [
+ *         {
+ *             xtype: 'checkbox',
+ *             cbind: {
+ *                 value: '{!persistentProperty}',
+ *                 object: '{objectProp.foo}'
+ *                 dynamic: (get) => get('numericProp') + 1,
+ *             },
+ *         },
+ *         {
+ *             // empty cbind so that subitems are reached
+ *             cbind: {},
+ *             items: [
+ *                 {
+ *                     xtype: 'textfield',
+ *                     cbind: {
+ *                         value: '{objectProp.bar}',
+ *                     },
+ *                 },
+ *             ],
+ *         },
+ *     ],
+ * });
+ */
+
 Ext.define('Proxmox.Mixin.CBind', {
     extend: 'Ext.Mixin',
 
-- 
2.30.2