TL; TR; ниже

Я имею дело с огромным приложением, в котором все сделано универсальным, чтобы его можно было легко расходовать. Одна из составляющих - диалог. Прежде чем вы ответите, используйте шаблоны ngInclude или angular, позвольте мне объяснить, как они работают и почему мы хотели бы их придерживаться.

Последовательность создания этого диалога:

  1. Откуда-то в javascript вызывается функция javascript.
  2. Это создает контейнер для диалога. Положение, ширина, высота, серый фон и т. Д.
  3. Как только он появится, появится индикатор загрузки, в то время как запрос GET будет выполнен в серверной части.
  4. Во внутреннем действии предоставляется имя представления и модель.
  5. Это представление (файл .cshtml) загружается в построитель строк. Чтобы дать вам представление о том, что происходит, вот фрагмент кода, в который загружается представление.

    var sb = new StringBuilder(1);
    using (StringWriter sw = new StringWriter(sb))
    {
        .....
        var helper = new HtmlHelper(viewContext, viewDataContainer);
        using (helper.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
        {
            helper.RenderPartial(viewName, model);
        }
        return sb.ToString();
    }
    
  6. Затем возвращается строка, в javascript она в конечном итоге устанавливается как html: diag.html(jsonResponse.data);

Теперь представление, которое я загружаю, содержит элементы angular, такие как ng-controller и скобки, чтобы показать что-то из этого контроллера. Вот .cshtml:

@model int
<div ng-controller="dialogGridColumnSelectionController as dgc" ng-init="dgc.init(@Model)">

    <table>
        <thead>
           ...
        <tbody>
        <tr ng-repeat="col in dgc.tableColumns">
            <td>
                <input type="checkbox" name="some" ng-value="dgc.hide"/>
            </td>
            <td>{{col.headerName}}</td>
            <td>{{col.Description}}</td>
        </tr>
        </tbody>
    </table>
</div>

Несколько утверждений:

  • ng-app был испробован позже, он не нужен здесь, потому что элемент <body> уже имеет его.
  • Диалог находится внутри элемента <body>.
  • Никаких ошибок, никаких угловых предупреждений.
  • {{col.headerName}} показывает именно то, как показано, поэтому angular не работает.
  • Контроллер и все остальные необходимые файлы javascript уже загружены на страницу, с которой открывается это диалоговое окно. Тоже пробовал сюда добавить, без разницы. Я также попытался снова загрузить туда angular, это дает мне предупреждение, что я tried to load it more than once. Итак, скрипты есть.

Теперь я как бы сомневался, что это сработает с самого начала, но я просто хочу убедиться, прежде чем мы начнем серьезную переработку диалогов.

Итак, мой вопрос: возможно ли это? Может ли представление, инициированное из .html() (в javascript) иметь angular? Как мне "запустить" Angular? Или почему он не работает с сгенерированным html?

TL; TR и EDIT:

Покопавшись, я в конце концов сделал следующее:

dialog.html(jsonResponse.data);//dialog is a created jquery element, jsonResponse.data contains the `.cshtml` content
if (options.angularCompile && options.angularScope) {//I've set them in options
    options.angularCompile(dialog)(options.angularScope);//= $compile(dialog)($scope) or $compile(dialog.contents())($scope)
}

Из приведенного выше html он действительно запускает функцию init. Эта функция правильно загружает данные (с других внедренных фабрик).

var self = this;

this.tablePageID = 0;
this.tableColumns = [];

$scope.hello = "hii";
this.init = function (tablePageID) {
    self.tablePageID = tablePageID;
    self.tableColumns = gridTableFactory.getTableColumns(tablePageID);
}

Но после завершения и отображения диалогового окна у него все еще нет угловой работы.

example

Стоит отметить, что ng-repeat выполнил свою работу с самого начала, никаких элементов нет. Похоже, компилируется и забывает.

0
CularBytes 4 Янв 2017 в 18:46
Используйте $ compile перед добавлением html. И постарайтесь сузить свой вопрос - 99% вопросов должны касаться бэкэнда или интерфейса, а не обоих сразу.
 – 
Petr Averyanov
4 Янв 2017 в 20:33
В конце концов, мой вопрос касается внешнего интерфейса. Angular недоступен в этой части кода, но завтра я взломаю его и посмотрю, поможет ли это.
 – 
CularBytes
4 Янв 2017 в 22:09
Я использовал $ compile, кажется, на первый взгляд работает. Он компилирует, выполняет некоторый код контроллера, успешно использует внедренные фабрики. Но когда диалог открыт, по-прежнему отображается простой html. угловые скобки продолжают появляться. Он как бы бежит и забывает.
 – 
CularBytes
5 Янв 2017 в 12:27
Убедитесь, что исходный скомпилированный HTML-код не копируется как новые элементы DOM при отображении диалогового окна. После открытия диалогового окна вам может потребоваться запустить службу $ compile.
 – 
KoenW
5 Янв 2017 в 12:48
Хой Коэн, да, это последнее, что происходит. Фактически, диалог уже отображается с индикатором загрузки. После загрузки cshtml он отредактирует содержимое диалогового окна. Событие open начинается с var diag = $(this);. response.data применяется к существующему диалогу .html(), а затем я $compile его.
 – 
CularBytes
5 Янв 2017 в 18:03

1 ответ

Лучший ответ

Попробуйте выполнить $scope.$apply(); после использования $compile. Возможно, вам потребуется сообщить angular, чтобы обновить его привязки. Также старайтесь избегать прямого использования jQuery и используйте вместо него angular.element("#....").

1
CularBytes 10 Янв 2017 в 14:44
Тьфу, я сделал $apply() внутри контроллера angular, дайджест уже был занят, так что я предположил, что это не нужно. Хотя для этого не требовалось angular.element().
 – 
CularBytes
10 Янв 2017 в 14:44