Красивый автоматический макет из 2-х ng-сеток (основной/подробности), ширина которых меняется в зависимости от содержимого (CSS во время выполнения)

Предыдущий вопрос SO: есть способ auto Adjust widths in ng-grid? описывает, как автоматически настроить ширину ng-grid, отрегулировав ширину каждого столбца так, чтобы он соответствовал самым длинным данным в любой строке этого столбца.

Я хочу сделать это на основе данных JSON, периодически получаемых с сервера, что означает, что содержимое сетки и, следовательно, ширина время от времени будут меняться. Ссылочное решение должно справиться с этим.

Однако у меня есть 2 сетки (главная/детальная), которые я буду отображать рядом на странице.

+------------+      +-----------+
| master     |      | detail    |
+------------+      +--------- -+
| customer 1 |      | Order 1,a |
+------------+      +-----------+
| customer 2 |      | Order 1,b | 
+------------+      +-----------+
| customer 3 |      
+------------+      

что-то такое.

Проблема в том, что я хотел бы красиво разместить их на веб-странице. Скажем, левое и правое поля одинакового размера, чтобы сетки не нагревали край страницы, а имели небольшой отступ. Затем из сетки в центре, с некоторым пространством между ними.

Возможно, центры сеток, независимо от ширины, могут быть на 25% и 75% страницы соответственно (или на 30% и 70% и т. д.).

--------------------------------------------
|                                          |
|      +---+             +_____________+   |
|      |   |             |             |   |
|      +---+             +_____________+   |
|                                          |
--------------------------------------------

Я могу разработать эстетику и математику, хотя вопросы приветствуются.

Я уверен, что я не первый, кто делает что-то подобное. Мой вопрос как?

Я думаю, что мне, возможно, придется пошалить и поместить встроенный CSS типа style="width:{{masterGridthWidth}} непосредственно в мой HTML и иметь что-то вроде ng-style="getMasterGridthWidth()" в элементе, чтобы позволить мне эффективно генерировать CSS во время выполнения.

Это вообще возможно (я не думаю, что ng-class поможет)? Есть ли лучший способ сделать это?


[Обновление] Я согласен с @MichalCharemza в том, что 1) лучше использовать чистое исправление CSS, если я могу, а не использовать JS, и 2) сетки с фиксированной шириной были бы лучшим UX.

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

Откуда берутся эти ширины 1198 пикселей (похоже на официальный ng-grid.css) и как я могу их переопределить? Я попытался добавить `style="width:25%" в свой частичный файл. Я даже завернул сетку в другой DIV шириной 25%, но безрезультатно.

Я застрял :-(

<div class="ngTopPanel ng-scope" ng-class="{'ui-widget-header':jqueryUITheme, 'ui-corner-top': jqueryUITheme}" ng-style="topPanelStyle()" style="width: 1198px; height: 45px;">
    <div class="ngGroupPanel ng-hide" ng-show="showGroupPanel()" ng-style="groupPanelStyle()" style="width: 1198px; height: 32px;">
        <div class="ngGroupPanelDescription ng-binding" ng-show="configGroups.length == 0">Drag a column header here and drop it to group by that column.</div>
        <ul ng-show="configGroups.length > 0" class="ngGroupList ng-hide">
            <!-- ngRepeat: group in configGroups -->
        </ul>
    </div>
    <div class="ngHeaderContainer" ng-style="headerStyle()" style="width: 1198px; height: 45px;">
        <div ng-header-row="" class="ngHeaderScroller" ng-style="headerScrollerStyle()" style="height: 45px;"><!-- ngRepeat: col in renderedColumns --><div ng-style="{ height: col.headerRowHeight }" ng-repeat="col in renderedColumns" ng-class="col.colIndex()" class="ngHeaderCell ng-scope col0 colt0">
    <div class="ngVerticalBar" ng-style="{height: col.headerRowHeight}" ng-class="{ ngVerticalBarVisible: !$last }">&nbsp;</div>
    <div ng-header-cell=""><div class="ngHeaderSortColumn  ngSorted" ng-style="{'cursor': col.cursor}" ng-class="{ 'ngSorted': !col.noSortVisible() }" draggable="true" style="cursor: pointer;">
    <div ng-click="col.sort($event)" ng-class="'colt' + col.index" class="ngHeaderText ng-binding colt0">Vehicle type</div>
    <div class="ngSortButtonDown ng-hide" ng-click="col.sort($event)" ng-show="col.showSortButtonDown()"></div>
    <div class="ngSortButtonUp" ng-click="col.sort($event)" ng-show="col.showSortButtonUp()"></div>
    <div class="ngSortPriority ng-binding"></div>
    <div ng-class="{ ngPinnedIcon: col.pinned, ngUnPinnedIcon: !col.pinned }" ng-click="togglePin(col)" ng-show="col.pinnable" class="ng-hide ngUnPinnedIcon"></div>
</div>
<div ng-show="col.resizable" class="ngHeaderGrip ng-scope ng-hide" ng-click="col.gripClick($event)" ng-mousedown="col.gripOnMouseDown($event)"></div>
</div>
</div><!-- end ngRepeat: col in renderedColumns --></div>
    </div>
    <div ng-grid-menu=""><div ng-show="showColumnMenu || showFilter" class="ngHeaderButton ng-scope ng-hide" ng-click="toggleShowMenu()">
    <div class="ngHeaderButtonArrow"></div>
</div>
<div ng-show="showMenu" class="ngColMenu ng-scope ng-hide">
    <div ng-show="showFilter" class="ng-hide">
        <input placeholder="Search..." type="text" ng-model="filterOptions.filterText" class="ng-pristine ng-valid">
    </div>
    <div ng-show="showColumnMenu" class="ng-hide">
        <span class="ngMenuText ng-binding">Choose Columns:</span>
        <ul class="ngColList">
            <!-- ngRepeat: col in columns | ngColumns --><li class="ngColListItem ng-scope" ng-repeat="col in columns | ngColumns">
                <label class="ng-binding"><input ng-disabled="col.pinned" type="checkbox" class="ngColListCheckbox ng-pristine ng-valid" ng-model="col.visible">Vehicle type</label>
                <a title="Group By" ng-class="col.groupedByClass()" ng-show="col.groupable &amp;&amp; col.visible" ng-click="groupBy(col)" class="ngGroupIcon"></a>
                <span class="ngGroupingNumber ng-binding ng-hide" ng-show="col.groupIndex > 0">0</span>          
            </li><!-- end ngRepeat: col in columns | ngColumns -->
        </ul>
    </div>
</div>
</div>
</div>

person Mawg says reinstate Monica    schedule 30.04.2014    source источник
comment
Просто чтобы проверить, что вы думаете о UX этого? Мое чутье подсказывает, что может быть довольно много прыжков, если сетки меняют ширину в зависимости от их содержимого, которое периодически меняется. Я подозреваю, что стандартная сетка, скажем, 25%/75%, с небольшим отступом, была бы хорошим решением.   -  person Michal Charemza    schedule 02.05.2014


Ответы (1)


Во-первых, согласно моему комментарию, я не уверен, стоит ли периодически и автоматически изменять ширину самих сеток с точки зрения пользователя. Во-вторых, если это можно решить только с помощью CSS, при условии, что CSS прост и удобен в сопровождении, я бы не стал использовать Javascript для стилизации.

So...

Вы не кажетесь слишком определенным в том, что вы подразумеваете под «симпатичным», но один из способов добиться если не красоты, то аккуратности — обеспечить постоянное расстояние между элементами (указанное в пикселях), но ширина элементов может быть немного отзывчивым (по существу, к ширине браузера)

Существуют системы сетки CSS, которые могут это сделать (например, Twitter Bootstrap), но если вы ориентируетесь на современные браузеры, то использование гибких блоков CSS может дать способ сделать это с помощью минимум кода, а не дополнительные зависимости.

Если ваша HTML-структура настолько проста, насколько это возможно:

<div class="window">
  <div class="master">
    <p>Master</p>
  </div>
  <div class="detail">
    <p>Detail</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin tellus nisl, tristique a nisi sed, facilisis suscipit ligula. Ut lectus arcu, mollis sit amet faucibus in, hendrerit ac nisl.</p>
  </div>
</div>

Затем CSS для создания простого макета с двумя столбцами (что, по сути, является тем, что вы просите для описания выше, довольно короткий, с использованием display: flex и обычного свойства width.

/* Layout */
.window {
  display: -webkit-flex;     /* Safari */
  display: flex;
}
.master {
  width: 25%;
}
.detail {
  width: 75%;
}

/* Spacing */
.window, .master, .detail {
  padding: 20px;
}
.detail {
  margin-left: 20px;
}

Вы можете посмотреть демонстрацию этого. Одно приятное преимущество заключается в том, что поведение по умолчанию модели flexbox заключается в том, что каждый из дочерних элементов (в данном случае .master и .detail) имеет одинаковую высоту, высоту самого высокого из 2.

макет flexbox с 2 столбцами

Для интеграции с ngGrid практически ничего не нужно делать. Единственное, что нужно сделать, это дать контейнерам master/detail display: flex, чтобы они также были родительским flex-контейнером для экземпляров ngGrid. Это дает ngGrid экземплярам поведение по умолчанию, когда их высота равна высоте их гибкого родителя.

Вы можете посмотреть демонстрацию flexbox, интегрированного с ngGrid.

макет flexbox с 2 столбцами, интегрированный с ngGrid.

person Michal Charemza    schedule 02.05.2014
comment
+1 Вау, ты много труда вложил в это. Спасибо. Моя проблема, похоже, связана с жестко закодированной шириной в файле Angular CSS, я обновил вопрос, так как здесь слишком много места. И, да, я думаю, что сетки с фиксированной шириной, вероятно, были бы лучше. - person Mawg says reinstate Monica; 02.05.2014
comment
Я никогда не понимал, что не так с моим кодом (HTML/CSS). Я просто скопировал ваш Plunk в свой код, связал свои 2 сетки с вашим HTML, затем удалил свой HTML и CSS, и все в порядке! Спасибо! - person Mawg says reinstate Monica; 03.05.2014