Когда я только начинал знакомиться с ExtJS, для меня было несколько дико, что такой крупный каркас веб-разработки не содержит никаких средств для использования гиперссылок в пользовательском интерфейсе (по крайней мере наравне с кнопками, панельками и прочими более сложными контролами, которые можно внедрить куда угодно). Как это часто бывает, фреймворк, который дает простой путь для сложных вещей, создает сложности в тех местах, где их и не ожидаешь.
Разумеется, средствами Ext.Element (кроссбраузерной обертки вокруг dom-элементов) можно в режиме выполнения сделать инъекцию любого фрагмента HTML, но той гибкости и легкости, с которой другие контролы можно вставить, например, в тулбар, панельку или другой контейнер, добиться будет очень сложно.
И вот недавно, работая над прототипом одного приложения, я «случайно» написал такой компонент. Он очень прост, но, как мне кажется, многим мог бы облегчить жизнь.
Ниже прилагается его код и краткий разбор.
Custom.Hyperlink = Ext.extend(Ext.BoxComponent, { constructor: function (config) { config = config || {}; Ext.apply(this, config); Custom.Hyperlink.superclass.constructor.call(this, config); this.on('afterrender', this.createHref, this); this.addEvents('clicked'); }, hrefTpl: '<a href="#" onclick="Ext.getCmp(\'{0}\').notifyClicked(); return false;">{1}</a>', createHref: function () { var tpl = new Ext.Template(this.hrefTpl), html = tpl.apply([this.getId(), this.text]); this.el.update(html); }, notifyClicked: function () { this.fireEvent('clicked', this); } } ); Ext.reg('hyperlink', Custom.Hyperlink);
Такая гиперссылка добавляется в контейнер так же, как и любой другой стандартный компонент; взаимодействие с окружающей средой происходит в привычном событийно-ориентированном стиле.
Ссылка не привязана к заранее заданному dom id, но синтаксически гарантируется, что метод, вызванный в 'onclick' ссылки будет вызван от имени правильного компонента (как известно, при вызове метода method в виде A.method() гарантируется, что this внутри метода будет указывать на A)
Ниже приводится пример использования такого компонента.
Custom.SearchPanel = Ext.extend(Ext.Panel, { initComponent: function () { Ext.apply(this, { … //skipped tbar: [{ xtype: 'hyperlink', text: 'Show advanced', listeners: { scope: this, clicked: this.showAdvancedForm } } ] } ); Custom.SearchPanel.superclass.initComponent.call(this); }, showAdvancedForm: function () { Ext.Msg.alert('Clicked!'); } } );
В идеале для гиперссылки следует сделать возможность разрешать/запрещать экранирование HTML-небезопасных символов при задании свойства text. Делается это тривиально с помощью стандартной функции Ext.util.Format.htmlEncode(). Такое улучшение я предлагаю читателю в качестве небольшого упражнения.

