无法在angular5中解析类型文档

时间:2018-03-27 12:51:28

标签: angular angular5

我想在点击 body 标记上的按钮时动态添加CSS类。所以我使用角度的DOCUMENT对象。这是代码

import { DOCUMENT } from "@angular/platform-browser";

... component code

constructor( @Inject(DOCUMENT) private document: Document) { }

addClass() {
    this.document.body.classList.add("any_class");
}

但这显示错误

Metadata collected contains an error that will be reported at runtime: Could not resolve type Document.
[0]   {"__symbolic":"error","message":"Could not resolve type","line":50,"character":53,"context":{"typeName":"Document"}}
[0]     at \node_modules\@angular\compiler-cli\src\metadata\collector.js:664:27
[0]     at Array.forEach (<anonymous>)
[0]     at validateMetadata (D:\QPP Workspace\QWC\QWC\node_modules\@angular\compiler-cli\src\metadata\collector.js:652:42)
[0]     at MetadataCollector.getMetadata (D:\QPP Workspace\QWC\QWC\node_modules\@angular\compiler-cli\src\metadata\collector.js:507:17)
[0]     at LowerMetadataCache.getMetadataAndRequests (ProjectPath\node_modules\@angular\compiler-cli\src\transformers\lower_expressions.js:264:39)
[0]     at LowerMetadataCache.ensureMetadataAndRequests (ProjectPath\node_modules\@angular\compiler-cli\src\transformers\lower_expressions.js:209:27)
[0]     at LowerMetadataCache.getRequests (ProjectPath\node_modules\@angular\compiler-cli\src\transformers\lower_expressions.js:204:21)
[0]     at ProjectPath\node_modules\@angular\compiler-cli\src\transformers\lower_expressions.js:146:36
[0]     at ProjectPath\node_modules\typescript\lib\typescript.js:2601:86
[0]     at reduceLeft (ProjectPath\node_modules\typescript\lib\typescript.js:2274:30)
error Command failed with exit code 2.
[0]     at ChildProcess.exithandler (child_process.js:275:12)
[0]     at emitTwo (events.js:126:13)
[0]     at ChildProcess.emit (events.js:214:7)
[0]     at maybeClose (internal/child_process.js:925:16)
[0]     at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5)

问题是什么?我正在使用 angular5 。还有其他方法可以动态添加类吗?

3 个答案:

答案 0 :(得分:3)

如果使用类似的方法,则会出现此错误

@Inject(DOCUMENT) document: Document

将tsconfig.json中的编译器设置设置为

"angularCompilerOptions": {
  "strictMetadataEmit": true
}

事实证明,角度编译器在计算可注入参数的元数据时不理解类型Document,即使它理解了注入令牌DOCUMENT,而Typescript也理解类型{{1 }}。

在此处记录: https://github.com/angular/angular/issues/20351

我使用的解决方法是:

Document

这使用@Injectable({ providedIn: 'root' }) class MyService { constructor(@Inject(DOCUMENT) document?: any) { this._document = document as Document; } private _document?: Document; ... 作为注入签名(使角度满意),但为您提供了类内的Typescript类型。

答案 1 :(得分:2)

您可以直接在打字稿中使用//task page code public class TaskFragment extends android.support.v4.app.Fragment { private SQLiteDatabase db; private TaskAdapter taskAdapter; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_tasks, null); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); //db TaskDBHelper dbHelper = new TaskDBHelper(TaskFragment.this.getActivity()); db = dbHelper.getWritableDatabase(); RecyclerView recyclerView = view.findViewById(R.id.recyclerView); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(TaskFragment.this.getActivity())); taskAdapter = new TaskAdapter(TaskFragment.this.getActivity(), getAllItems()); recyclerView.setAdapter(taskAdapter); new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { removeItem((long) viewHolder.itemView.getTag()); } }).attachToRecyclerView(recyclerView); // view.findViewById(R.id.add_task_fab).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { openAddTask(); } }); } private void removeItem(long id) { db.delete(TaskContract.TaskEntry.TABLE_NAME, TaskContract.TaskEntry._ID + "=" + id, null ); taskAdapter.swapCursor(getAllItems()); } public Cursor getAllItems() { TaskDBHelper dbHelper = new TaskDBHelper(TaskFragment.this.getActivity()); db = dbHelper.getWritableDatabase(); return db.query( TaskContract.TaskEntry.TABLE_NAME, null, null, null, null, null, TaskContract.TaskEntry.COLUMN_TIMESTAMP + " DESC" ); } public void openAddTask() { Intent intent = new Intent(TaskFragment.this.getActivity(), AddTask.class); startActivityForResult(intent, 1); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1) { if(resultCode == Activity.RESULT_OK){ taskAdapter.swapCursor(getAllItems()); } } } } 而无需任何导入。

只需:document

答案 2 :(得分:0)

您可以在组件的装饰器之前添加“ / ** @dynamic * /”:

/** @dynamic */
@Component({

如此处https://github.com/angular/angular/issues/20351#issuecomment-344009887和此处https://angular.io/guide/aot-compiler#strictmetadataemit

所述,以抑制错误