≡

Question/Feature requests for stateRestore default state

Question/Feature requests for stateRestore default state

WernfriedWernfried Posts: 57Questions: 12Answers: 0

Is it possible in stateRestore to set the default/inital state by option or API? I did not find a simple way to do it.

A possible implementation might be an extension of https://datatables.net/ref/core/option/stateRestore.defaults property:

  • true - The end user can set a state to be the default state
  • false - The end user cannot set a default state.
  • "string" - The name of the state to be loaded (if existing) by default

Then the default state could be retrieved for example from URL parameters:

const urlParams = new URLSearchParams(window.location.search);
new DataTable('#myTable', {
    layout: {
        topStart: {
            buttons: ['stateCreate', 'statesList']
        }
    },
    stateRestore: {
        defaults: urlParams.get('state')
    }
});

If such feature becomes available, I think I could convince my manager to go for DataTables Plus

Wernfried

Answers

  • allanallan Posts: 66,158Questions: 1Answers: 11,033 Site admin

    If such feature becomes available, I think I could convince my manager to go for DataTables Plus

    You have my attention ;)

    In all seriousness, what you are looking for is already available (assuming I've understood correctly). To have initial states in StateRestore you use stateRestore.predefined and you can set isDefault on the one you want to be loaded up by default.

    Here is a little example.

    Does that match what you want?

    Allan

  • WernfriedWernfried Posts: 57Questions: 12Answers: 0

    Not really. In my application the user will create the states by himself, I don't know the individual preferences and needs of my users. Yes, the user can select which state should be the default - but just one. The user may have 2 or 3 states which they use frequently and they want to open them with one click, typically with a bookmark in their browser or even as part of their start-pages.

    Wernfried

  • allanallan Posts: 66,158Questions: 1Answers: 11,033 Site admin

    Ah I see - many thanks for the clarification. How about if there were an option for when you change state it sets either a search location or a query parameter on the URL. That way you could book mark that URL and StateRestore would check the search or query (depending on the configuration) for that parameter and use the appropriate state. It could be something like ?dtsr=1 where 1 is the state id. Would that suit?

    Allan

  • WernfriedWernfried Posts: 57Questions: 12Answers: 0

    Yes, that's exactly what I was looking for. At the moment I create a custom button where I loop over all state properties and add each key-value as query parameter on the URL. A single query parameter (i.e the state id) would make much more sense.

    Wernfried

  • allanallan Posts: 66,158Questions: 1Answers: 11,033 Site admin
    Answer ✓

    Perfect - I think I can add that in fairly short order. I'm in the middle of some SearchPanes updates at the moment, but I'll look at implementing this and get back to you when it is ready.

    Allan

  • allanallan Posts: 66,158Questions: 1Answers: 11,033 Site admin
    Answer ✓

    I've just released StateRestore 2.2.0 which introduces a new stateRestore.bookmark option.

    You can see a set of example here - they walk through the various options for how this new feature can be configured.

    If you get a chance to try it out, I'd welcome any feedback you have.

    Regards,
    Allan

  • WernfriedWernfried Posts: 57Questions: 12Answers: 0

    Hi Allan

    From documentation, this looks really great, thank you.
    I will test it in the next days or weeks.

    Best Regards
    Wernfried

  • WernfriedWernfried Posts: 57Questions: 12Answers: 0

    I started implementation of this feature, really nice.

    Just a few minor styling points when you use the extension with Bulma styling. When you create a new state, then you get a dialog like this:

    Is this layout by intention? I mean, it is working but it is not award winning beautiful. What about this one?

    <div class="field">
        <label class="label">Behavior:</label>
        <div class="control">
            <label for="dtsr-default" style="gap:12px;" class="is-flex is-align-items-baseline">
                <input type="checkbox">
                <span>Default
                    <p class="help">The state that is selected as the default will be<br>used automatically when the page is loaded.</p>
                </span>
            </label>
        </div>
        <div class="control">
            <label for="dtsr-default" style="gap:12px;" class="is-flex is-align-items-baseline">
                <input type="checkbox">
                <span>Share
                    <p class="help">Other users of the system will be able to use states that you share.<br>They will not be able to edit the state.</p>
                </span>
            </label>
        </div>
    </div>
    
    

    Or maybe, use the title attribute on the check-box.

    Font Awesome is not part of Bulma Framework, they are just used as example. To get nicer drop-down indicators you may replace

    .fa-angle-down::before {
      content: "▼";
    }
    

    by

    .fa-angle-downx {
      display: inline-block;
      width: 1em;
      height: 1em;
      background-color: currentColor;
      -webkit-mask-image: var(--svg);
      mask-image: var(--svg);
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M7.41 8.58L12 13.17l4.59-4.59L18 10l-6 6l-6-6z'/%3E%3C/svg%3E");
    }
    

    Best Regards
    Wernfried

  • allanallan Posts: 66,158Questions: 1Answers: 11,033 Site admin
    Answer ✓

    I completely agree, that looks much better!

    The reason I didn't do that, or something similar, is that the Bulma documentation just has the label and inputs stacked, so I assumed that is what folks using Bulma were expecting the UI to look like by default, and it can then be tweaked if needed.

    Possibly I've got the wrong end of the stick with that though?

    Font Awesome is not part of Bulma Framework,

    I've made that mistake before. They use FA in their docs, so I made use of FA as well. I'll get that updated - thanks!

    Allan

  • WernfriedWernfried Posts: 57Questions: 12Answers: 0

    For me the Bulma .help class is just a generic class you can use anywhere

    .help {
      display: block;
      font-size: var(--bulma-help-size);
      margin-top: 0.25rem;
    }
    

    Sure, it makes sense to put a help text below a text-input or a dropdown-input. But it's stupid to put it below a tiny checkbox element. So, why not putting it below the label?

    I did not find any sample or documentation where .help is used in combination with a checkbox. Most likely the Bulma developers did not have this combination in their mind. They provide generic Flexbox helpers, for me that's an invitation to utilize all nice functions you have with Flexbox.

    Wernfried

  • allanallan Posts: 66,158Questions: 1Answers: 11,033 Site admin
    Answer ✓

    Their documentation shows the labels and inputs stacked, and the checkbox example there is an exception though, as its has the label to the right:

    I don't think that would work for the StateRestore use case, and I prefer your styling. As I say, I used a stacked layout since it seemed to be what their documentation shows. I'll check and see if the classes and markup I provide options for in StateRestore allow an alternative to easily be set.

    Allan

  • WernfriedWernfried Posts: 57Questions: 12Answers: 0
    edited October 28

    One more point. It took me some time to understand the concept of these "incremental" states. More than one state can be active at the same time, which makes the entire feature more powerful.

    But when you use stateRestore.include then you have a small issue.

    Assume, you create a state with (only) property columnVisibility and another one with(only) property columnSearch and you set isDefault: true on both of them - which is accepted on local and I do accept it on ajax.

    Then I would expect DT to load both states, and applies columnVisibility and columnSearch at the inital view. However, DT loads only the first one, the user cannot control the order, I guess.

    I see several possible solutions:

    1. isDefault: true must be set on one state only, setting it on more than one state is not possible
      In this case, you may also enforce to enable all state properties - which is maybe not applicable for all use-cases
    2. At initialisation DT loops over all states where isDefault == true and applies them. Of course, the user may have created several states which are contradicting to each other and the final result depends on the order of reading and may not match the expectation of the user.
    3. Instead of having a isDefault attribute on state level, you may set it at property level. Each property must have not more than one isDefault. Honestly, this would seem to be the most advanced solution - but maybe an overkill and many user might be overwhelmed by it.

    Thus, I would suggest option (2) and just take the risk, that users may create multiple default states which are contradicting to each other.

    The bookmarks may be also extended to load more than just one state, i.e. URL parameter ?dtsr=1&dtsr=2 should load state 1 and state 2. Of course, for hash location # this wold not be possible easily.

    Kind Regards
    Wernfried

  • WernfriedWernfried Posts: 57Questions: 12Answers: 0

    A few more comments.

    The stored state always contains length property, no matter if {include: {paging: ...}} is true or false.
    I would expect length exists only for {include: {paging: true}}. Perhaps it is not relevant.

    One more issue:
    The logic of active states is not fully correct. I have these three states:

    'To Do' = '{"columns":[{"name":"id"},{"name":"action"},{"name":"status"},{"name":"owner"},{"name":"type"},{"name":"title"},{"name":"impact"},{"name":"planStartDate"},{"name":"planEndDate"},{"name":"affected"},{"name":"backoffice"},{"name":"pendingApproval"},{"name":"preset"}],"length": 171,"childRows":[],"columnControl":{"id":{"searchInput":{"logic":"equal","type":"num","value":""}},"status":{"searchList":[]},"owner":{"searchList":[]},"type":{"searchList":[]},"title":{"searchInput":{"logic":"contains","type":"text","value":""}},"impact":{"searchList":[]},"planStartDate":{"searchInput":{"logic":"equal","type":"date","value":""},"searchList":[]},"planEndDate":{"searchInput":{"logic":"equal","type":"date","value":""},"searchList":[]},"affected":{"searchInput":{"logic":"contains","type":"text","value":""}},"backoffice":{"searchList":[]},"pendingApproval":{"searchList":[]},"preset":{"searchList":["todo"]}}}'
    
    'My Team - CC only' = '{"columns":[{"name":"id"},{"name":"action"},{"name":"status"},{"name":"owner"},{"name":"type"},{"name":"title"},{"name":"impact"},{"name":"planStartDate"},{"name":"planEndDate"},{"name":"affected"},{"name":"backoffice"},{"name":"pendingApproval"},{"name":"preset"}],"length": 171,"childRows":[],"columnControl":{"id":{"searchInput":{"logic":"equal","type":"num","value":""}},"status":{"searchList":[]},"owner":{"searchList":["section:6ad8b4e5892caaa1eb53cbfe"]},"type":{"searchList":[]},"title":{"searchInput":{"logic":"contains","type":"text","value":""}},"impact":{"searchList":[]},"planStartDate":{"searchInput":{"logic":"equal","type":"date","value":""},"searchList":[]},"planEndDate":{"searchInput":{"logic":"equal","type":"date","value":""},"searchList":[]},"affected":{"searchInput":{"logic":"contains","type":"text","value":""}},"backoffice":{"searchList":[]},"pendingApproval":{"searchList":[]},"preset":{"searchList":["todo"]}}}'
    
    'My Team' = '{"columns":[{"name":"id","visible":true},{"name":"action","visible":true},{"name":"status","visible":true},{"name":"owner","visible":true},{"name":"type","visible":true},{"name":"title","visible":true},{"name":"impact","visible":true},{"name":"planStartDate","visible":true},{"name":"planEndDate","visible":true},{"name":"affected","visible":true},{"name":"backoffice","visible":true},{"name":"pendingApproval","visible":true},{"name":"preset","visible":false}],"length":171,"order":[["id","desc"]],"search":{"boundary":false,"caseInsensitive":true,"columns":[0,1,2,3,4,5,6,7,8,9,10,11,12],"exact":false,"regex":false,"return":false,"search":"","smart":true},"searchGroups":[],"time":1793220170471,"childRows":[],"colReorder":[0,1,2,3,4,5,6,7,8,9,10,11,12],"columnControl":{"id":{"searchInput":{"logic":"equal","type":"num","value":""}},"status":{"searchList":[]},"owner":{"searchList":["section:6ad8b4e5892caaa1eb53cbfe"]},"type":{"searchList":[]},"title":{"searchInput":{"logic":"contains","type":"text","value":""}},"impact":{"searchList":[]},"planStartDate":{"searchInput":{"logic":"equal","type":"date","value":""},"searchList":[]},"planEndDate":{"searchInput":{"logic":"equal","type":"date","value":""},"searchList":[]},"affected":{"searchInput":{"logic":"contains","type":"text","value":""}},"backoffice":{"searchList":[]},"pendingApproval":{"searchList":[]},"preset":{"searchList":["todo"]}}}'
    

    In my table I would expect all three states as active, but I get only 'To Do' and 'My Team - CC only' - even when I load 'My Team' explicitly!

    Looks like, if fails when comparing the visible property. Visibility of columns had not been touched at all, they are all default.

    Kind Regards
    Wernfried

  • WernfriedWernfried Posts: 57Questions: 12Answers: 0

    Hi Allan

    You can forget the last paragraph of my previous post regarding the unclear active/non-active states. It was a mess in my data.

    However, this part is still valid

    The stored state always contains length property, no matter if {include: {paging: ...}} is true or false.
    I would expect length exists only for {include: {paging: true}}. Perhaps it is not relevant.

  • allanallan Posts: 66,158Questions: 1Answers: 11,033 Site admin
    Answer ✓

    Thanks for the update. Regarding the page length issue - StateRestore has pageStart and pageLength options in the stateRestore.include property.

    When I started on StateRestore 2 I did actually just have a single paging option there, but while developing and testing it, I decided to split it into two parts as I felt that provided more utility.

    I'm afraid that the error here is in the documentation which is an artefact of that history. I've committed a fix for that.

    Allan

Sign In or Register to comment.