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.
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.
After understanding the structure, start looking for problems. First, open Console.log when the outermost component submits data, and print the log:
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:
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:
(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:
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:
By searching level by level, there is no relevant HTML code, so it is concluded that this is achieved internally ng-autocomplete
.
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:
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:
Now look at the output result is null:
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.
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:
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:
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:
Add a layer of judgment logic directly to it: if it is an empty string, assign Null directly, and the others remain unchanged:
Refresh again, the function has been implemented:
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!)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。