5

Zero, the problem recurs

The difficulty in writing Debug articles is how to let readers who have not been in contact with this project understand what they are doing, understand the requirements of this function, how the problems in the text appear, and how to fix them. Therefore, the final effect of the articles recording the troubleshooting process is often not as good as the tutorial articles. If readers who have not written this code can understand the article, it means that an article has been successfully written.

May-23-2022 17-13-23.gif

As shown in the GIF, what was meant to be a normal form with non-null validators added to all but the last "parking space number" field.
In order to automatically pop up candidate information for the two fields of "vehicle owner" and "vehicle brand", the Angular autocomplete component is used.
The bug here is that these two fields can still be submitted after clearing the data, and the information before clearing is still used when submitting.

Next, record the investigation process.

1. Analysis component

To simplify the description, take the vehicle brand as an example.
First locate the component according to the route and find the field of the vehicle brand:

 // 车辆编辑组件
// 车辆品牌的输入框
<div class="mb-3 row">  
  <label class="col-sm-2 col-form-label  text-right">车辆品牌<code>*</code></label>  
  <div class="col-sm-10">  
    <app-vehicle-brand-auto-complete [formControlName]="formKeys.vehicleBrand"></app-vehicle-brand-auto-complete>  
  </div></div>

Through app-vehicle-brand-auto-complete , you can see that the component is encapsulated and passed in formControl, we need to find the encapsulated component again.

 // app-vehicle-brand-auto-complete组件
<yz-auto-complete [formControl]="formControl" [items]="items"  
                  (doSearchKeyChange)="onSearchKeyChange($event)"></yz-auto-complete>

There is only one line of code, and it is encapsulated again, passing in formControl and items (a list of vehicle brands),
So we still need to find the yz-auto-complete component:

 // yz-auto-complete组件
<div class="ng-autocomplete">  
  <ng-autocomplete (inputChanged)='onChangeSearch($event)'  
                   (selected)='selectEvent($event)'  
                   [data]="items"  
                   [debounceTime]="500"  
                   [itemTemplate]="itemTemplate"  
                   [ngModel]="formControl.value"  
                   [searchKeyword]="keyword">  
  </ng-autocomplete>  <ng-template #itemTemplate let-item>  
    <a [innerHTML]="item.name"></a>  
  </ng-template></div>

This time I finally see Angular built-in components.

To sum up, this form uses multiple layers of nesting dolls and passes in form fields, and the innermost layer uses Angular's built-in ng-autocomplete.

Pasted image 20220523173321.png

After understanding the structure, start looking for problems. First, open Console.log when the outermost component submits data, and print the log:

Pasted image 20220523173543.png

After testing, it was found that there are two ways to enter the situation input box, one is to click the X number on the right, and the other is to manually delete the information, such as GIF:

May-23-2022 17-37-14.gif
May-23-2022 17-37-53.gif

Commit after deletion, the results of these two ways are different:

(1) If you click the X number to delete, the output information is still the original information, you can guess that the data is not deleted at all:
Pasted image 20220523173941.png

(2) If the information is manually cleared, it is more interesting. The output information is an empty string, but the save is successful, and the validator does not intercept it:
Pasted image 20220523174046.png

So what is ostensibly one bug is actually two.

2. Solve the problem

Let's first solve the first problem: why the data is not cleared after clicking the X number.
To think about this, we must first know who controls the two X numbers:
Pasted image 20220523174310.png
By searching level by level, there is no relevant HTML code, so it is concluded that this is achieved internally ng-autocomplete .

Pasted image 20220523174548.png
It is easy to see how the data is ejected through the code. When the data changes, it is triggered onChangeSearch($event) to update, and when the drop-down menu is selected, it is triggered selectEvent($event) to update.
From the GIF just now, it is not difficult to see that when the X number is clicked to clear, neither of these two events will be triggered, so no data is ejected, and the outermost component will be submitted normally.

We can speculate that since there are "change" and "select" events, there must also be "clear" events. Looking at the inner class, there are indeed:

Pasted image 20220523174925.png

This inputCleared() is the method that is triggered when emptying, so we only need to add a line and pass an empty string as event to update empty data when emptying:

Pasted image 20220523175456.png

Now look at the output result is null:
Pasted image 20220523175530.png

Now the clear button can be implemented.

Next, solve this more interesting thing: why can I still submit after clearing the data?

At first, I naively thought: Because there is something wrong with the writing somewhere, the Validator validator does not take effect in the subcomponent, so I add the validator to the FormControl of all the subcomponents, but this is useless at all (also a bit useful , revealing his ignorance).

Just when I thought I was about to get stuck, I suddenly remembered a detail:
If it is a new vehicle, when the component is just initialized, it cannot be saved without inputting data, indicating that the validator is working.
Pasted image 20220523180043.png
But as long as any data is entered, the save button will light up, and no matter how you clear it afterwards, it will not dim:
May-23-2022 18-01-54.gif

This got me thinking, could there be a problem with the value of the ejection?

When I took another look at the data printed on the console, it dawned on me:
Pasted image 20220523180422.png
Type object for the brand field! The name of the object is empty does not mean the object is empty! Therefore it is also impossible to trigger the validator!

So I found the processing logic of ejection, as expected, the object will also be assigned an empty string:
Pasted image 20220523180640.png

Add a layer of judgment logic directly to it: if it is an empty string, assign Null directly, and the others remain unchanged:
Pasted image 20220523181041.png

Refresh again, the function has been implemented:
May-23-2022 18-12-05.gif

At this point, Debug is completed.

3. Summary

At first, the focus was only on the validator, but there was no clue.
After calming down and thinking about it, I realized that it was the problem of the object.
DEBUG is a job that requires composure, be patient and don't be impetuous.
(I handed in the final paper today, Ness!)


LYX6666
1.6k 声望77 粉丝

一个正在茁壮成长的零基础小白