tempusfugit (128) [Avatar] Offline
#1
CHAPTER 4 Part 1

Page 64(68):
TWO-WAY DATA BINDING VERSUS ONE-WAY DATA BINDING
One-way data binding occurs when data captured is not synced from the model to the view when the input changes.
Erm ... I don't think that is the commonly accepted meaning of "one-way binding" (unless I'm just getting caught on the wording). React is the poster-child of one-way binding - it's built around rendering the model state to the view. When it comes to form elements you have to manually set up listeners for the input or change events to actively change the component's state (or dispatch action messages) - i.e. for reflecting view changes back into the model. So "one-way binding" typically implies that the library/framework automagically takes care of pushing the model state to the view while changes from the view have to be manually propagated back to the model. So in the simplest terms "one-way binding" means: "data changes are automagically propagated to the view (while changes from the view back to the model have to be explicitly implemented)".

So in the following example we have "one-way binding":
  <html>
    <head>
      <title>v-once demo</title>
      <script src="https://unpkg.com/vue"></script>  </head>
    <body>
      <div id="app"></div>
      <script type="text/javascript">
       new Vue({
         el: '#app',
         data: {
           value: true
         },
         methods: {
           toggle(){
             this.value = ! this.value;
           }
         },
         template: `<div>
             <header>
               <h1 v-text="value"></h1>
             </header>
             <button v-on:click="toggle">Toggle</button>
           </div>`
       });
      </script>
    </body>
  </html>


So the h1 element's textContent is "one-way bound" to "value". Whenever the model is changed through the console, like $vm0.value = false; the h1 element in the DOM is updated (after initializing $vm0 through selecting the root in Vue.js devtools).
Regardless, we can specify a property as one-way bound in Vue by using the v-once directive.
The v-once directive sets a one-time binding, not a one-way binding. In the above code use <h1 v-once v-text="value"></h1> - the h1 element is rendered once as "true" and never changed again regardless how often you click that "toggle" button (after the first change you'll have to keep refreshing Vue.js devtools to see that the button is indeed changing the model value).
tempusfugit (128) [Avatar] Offline
#2
CHAPTER 4 Part 2 of 2

Page 66(70):
4.1 Using v-model binding
Listing 4.1 A v-model directive with first and last name inputs – chapter-04/first-last.html

should likely be:
  <div class="form-group">
    <div class="col-md-6">
      <strong>First Name:</strong>
      <input v-model="order.firstName" class="form-control" />
    </div>
    <div class="col-md-6">
      <strong>Last Name:</strong>
      <input v-model="order.lastName" class="form-control" />
    </div>
  </div>
  <div class="col-md-12 verify">
    <pre>
      First Name: {{order.firstName}}
       Last Name: {{order.lastName}}
    </pre>
  </div>
i.e the <div class="form-group"> didn't exist before.

Page 69(73):
... tag at the bottom (figure 4.4). Reload the browser and your new form should look like figure 4.4.
The caption of the referenced figure is 4.3.

Figure 4.3 Adding in the Address, City, State and Zip form fields into our checkout page.

Additional markup to make it "look like" figure 4.3 is left as an exercise to the reader, i.e.:
    <div class="col-md-10 col-md-offset-1">
      <div class="panel panel-info">
        <div class="panel-heading">Pet Depot Checkout</div>
        <div class="panel-body">
          <div class="form-group">
            <div class="col-md-12">
              <h4><strong>Enter Your Information</strong></h4>
            </div>

            ...

          </div>
        </div>
      </div>
    </div>
  </div>

Page 71(75):
This HTML code can be added after the previous 4.5 listing code.
To get "the look" of figure 4.5, the code in Listing 4.7 has to be actually placed before the div wrapping the pre element.


Page 74(78)

4.2.1 Binding values to our check box
Just a Comment.

It's at this point that it suddenly dawned on me why I felt a bit "uneasy" when I started by modifying the markup. While superficially it makes sense to start there as it seems to be what is closest to the UI, it's goes against the more natural development progression of delaying changes that have dependencies that don't exist yet. For example, I think it would feel more natural to discuss the changes in Listing 4.10 Adding the sendGift property to the order object – chapter-04/prop-gift.js before moving on to the changes in the markup Listing 4.9 Binding true and false values to the gift check box – chapter-04/true-false.html which depend on the changes in listing 4.10 (even when it feels like 4.9 is the motivation for 4.10).

Maybe it's worth considering these type of dependencies when choosing the order of progression within any discussion.


Listing 4.10 Adding the sendGift property to the order object – chapter-04/prop-gift.js

and

Listing 4.12 Updating the order object with business and home – chapter-04/update- order.html

What are the gift and shipping options doing inside the order object? Listing 4.14 Adding the states property to the Vue instance data object – chapter- 04/states.html has its own state object - so let there be a giftOptions and shipMethods object - sure there are only two properties but JavaScript objects have always been used as reasonable facsimiles of Map objects (because Map Objects didn't exist until ES2015).

I get that it's a learning exercise but on an object level gift: (true | false) makes sense - gift: ('Send As A Gift'|'Do Not Send As A Gift') not so much.

It's at this point that I notice that the short-form of v-bind, ":" is used way back on page 31(35) in Using expressions in bindings without introduction.
  • fix that?
  • decide when the various directive short-forms should be introduced/mentioned (like "@" for v-on) even if they're not going to be used in the examples.


  • Page 77(81)Listing 4.13 Binding values to our select box – chapter-04/bind-select.html
    1 Assigns the v-bind directive value attribute to states.AL property
    2 The v-bind directive value attribute assigned to states.AR property
    "The v-bind directive assigns the value of states.AL to the value attribute", etc.


    Page 78(82)
    The v-for directive requires a special syntax in the form of state in states. states is the source data array, while the state is an alias for the array element that is being iterated on. In this case, state is Alabama, Arizona, California, and so on.
  • "state in states. states" looks perilously close to "state in states.states" i.e. "states.states"
  • The writeup first talks about iterating through a "source data array" - then the code iterates through object properties with the optional expanded object syntax (state,key) in states in order to access the property name - this can create a bit of a temporary disconnect until after the listing when this issue is finally addressed.


  • Page 79(83)
    The key value is an optional argument that specifies the index of the current item.
    "The optional second argument (key) contains the property name of the current item."


    Page 81(85)
    The v-for directive without the optional key

    I think it makes more sense to do the v-for directive example as it is introduced in the documentation under Basic Usage - with an array of objects. As far as I'm aware the enumeration order of object properties is not fixed anywhere in any ECMAScript specification. It seems the most JavaScript engines enumerate properties in the order of creation - but as that isn't required by any specification, relying on that ordering will fail the next time an engine optimization messes with it. This ultimately limits the usefulness of using v-for on plain objects if you care about item order.

    Also the example seems backwards - typically the long form label is displayed in the UI while the code value goes into the object.

       states: [
         {value: 'AL', text: 'Alabama'},
         {value: 'AR', text: 'Arizona'},
         {value: 'CA', text: 'California'},
         {value: 'NV', text: 'Nevada'}
       ],
    

      <div class="form-group">
        <div class="col-md-2">
          <strong>State:</strong>
          <select v-model="order.state" class="form-control">
            <option disabled value="">State</option>
            <option v-for="state in states"
              v-bind:value="state.value"
              v-text="state.text"></>
          </select>
        </div>
      </div>
    

    Also this point seems to be the perfect time to revisit/refactor the shipping method radio buttons in order to introduce the useful "template v-for".
      shipMethods: [
        {id: 'home', value: 'Home Address', text: 'Home'},
        {id: 'business', value: 'Business Address', text: 'Business'}
      ],
    

      <div class="form-group">
        <div class="col-md-6 boxes">
          <template v-for="ship in shipMethods">
            <input type="radio"
              v-bind:id="ship.id" v-bind:value="ship.value" v-model="order.method" />
            <label v-bind:for="ship.id" v-text="ship.text"></label>
          </template>
        </div>
      </div>
    
    


    4.3.1 Using the .number modifier
    The discussion doesn't address that the conversion is only a "best effort".
  • '123' becomes [number: 123]
  • '12a' becomes [number: 12]
  • '1a2' becomes [number: 1]
  • 'a12' becomes [string: 'a12']
  • The result is whatever parseFloat() would return - unless the result would be NaN - then the original string is returned (ironically typeof(NaN) === 'number' - so "not a number" is a magic value of type "number" indicating the lack of a number).


    Page 82(86)
    The text before Listing 4.20 The .trim modifier on first and last name – chapter-04/trim-mod.html and Listing 4.21 The .trim modifier on the address and city – chapter-04/trim-mod-add.html is a bit on the repetitive side. Probably the easiest solution is to just combine both listings into one.


    Page 85(89)
    You can use an alias in the expression on the current element being iterated on as well.
    The term "alias" here (and on page 80(84)) can very easily lead to confusion because some people may take that to mean "named parameter" - when in fact the v-for directive implements "positional parameters" to instantiate arguments for each iteration - parameters for which you can specify arbitrary names by which you reference the arguments (just like for normal function parameters/arguments).
  • The first argument is the value of the object property.
  • The second argument is the name of the object property.
  • The third argument is the index of the object property (which isn't consistent across JavaScript engine implementations).


  • The "item in enumerable" syntax is meant to emulate the in operator syntax.
  • The "(value, name, index) in object" syntax is meant to be reminiscent of an argument list (though at first it kind of reminded me of destructuring assignment - but JavaScript doesn't have anything resembling tuples, however it does have argument lists of arbitrary arity).

  • Erik Hanchett (17) [Avatar] Offline
    #3
    Thank again! I'll be updating chapter 4 soon with your input! This helps a lot! smilie