Dashboards & Visualizations

Delete button for KV store wont work

mwdbhyat
Builder

Hi there,

Im trying to make my JS button delete records from the KV store by key id. I can see it grabbing the token in the URL but it doesnt actually delete it. I copied it from the dev tutorial and ammended it a bit - im also only using XML.

JS :

require(
[
'jquery',
'splunkjs/mvc',
'splunkjs/mvc/tokenutils',
'splunkjs/mvc/searchmanager',
'splunkjs/mvc/savedsearchmanager',
'splunkjs/mvc/simplexml/urltokenmodel',
'splunkjs/mvc/postprocessmanager'

 ],
 function ($, mvc,TokenUtils,SearchManager,SavedSearchManager,UrlTokenModel,PostProcessManager) {


     // Delete Button Ref
     const delete_config_button = $(`<button id="deleteRecordButton" class="btn btn-primary my-btn">Delete Record</button>`);

     // Place it
        $('.dashboard-form-globalfieldset').append(delete_config_button);
     // Delete Button
        $("#deleteRecordButton").click(function() {
        // Get the value of the key ID field
        var tokens = mvc.Components.get("default");
        var form_keyid = tokens.get("KeyID");

        // Delete the record that corresponds to the key ID using
        // the del method to send a DELETE request
        // to the storage/collections/data/{collection}/ endpoint
        service.del("storage/collections/data/dashboard_input_settings/" + encodeURIComponent(form_keyid)) 

    });

         });
  • Any thoughts on why this isnt working?
  • Is there a way to make it refresh my table, without using JS savedsearch manager?

Thanks!

0 Karma
1 Solution

niketn
Legend

@mwdbhyat try the following code, I have added console logs and changed the click event handler. Check in browser inspector whether click event is getting triggered or not.

require(
    [
        'jquery',
        'splunkjs/mvc',
        'splunkjs/mvc/tokenutils',
        'splunkjs/mvc/searchmanager',
        'splunkjs/mvc/savedsearchmanager',
        'splunkjs/mvc/simplexml/urltokenmodel',
        'splunkjs/mvc/postprocessmanager'

    ],
    function ($, mvc, TokenUtils, SearchManager, SavedSearchManager, UrlTokenModel, PostProcessManager) {
        console.log("Inside KVStore JS");
        // Delete Button Ref
        const delete_config_button = $(`<button id="deleteRecordButton" class="btn btn-primary my-btn">Delete Record</button>`);
        // Place it
        $('.dashboard-form-globalfieldset').append(delete_config_button);
        // Delete Button
        $(document).on("click","#deleteRecordButton",function () {
            console.log("Delete button clicked");
            alert("Deleting...");
            // Get the value of the key ID field
            var tokens = mvc.Components.get("default");
            var form_keyid = tokens.get("KeyID");
            // Delete the record that corresponds to the key ID using
            // the del method to send a DELETE request
            // to the storage/collections/data/{collection}/ endpoint
            service.del("storage/collections/data/dashboard_input_settings/" + encodeURIComponent(form_keyid));
            alert("Deleted...");
        });
    });

If the KVStore JS loaded log is not present in your browser's console, then the JS May have syntax error. If anything does not work you would need to provide additional details from console log.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

View solution in original post

0 Karma

niketn
Legend

@mwdbhyat try the following code, I have added console logs and changed the click event handler. Check in browser inspector whether click event is getting triggered or not.

require(
    [
        'jquery',
        'splunkjs/mvc',
        'splunkjs/mvc/tokenutils',
        'splunkjs/mvc/searchmanager',
        'splunkjs/mvc/savedsearchmanager',
        'splunkjs/mvc/simplexml/urltokenmodel',
        'splunkjs/mvc/postprocessmanager'

    ],
    function ($, mvc, TokenUtils, SearchManager, SavedSearchManager, UrlTokenModel, PostProcessManager) {
        console.log("Inside KVStore JS");
        // Delete Button Ref
        const delete_config_button = $(`<button id="deleteRecordButton" class="btn btn-primary my-btn">Delete Record</button>`);
        // Place it
        $('.dashboard-form-globalfieldset').append(delete_config_button);
        // Delete Button
        $(document).on("click","#deleteRecordButton",function () {
            console.log("Delete button clicked");
            alert("Deleting...");
            // Get the value of the key ID field
            var tokens = mvc.Components.get("default");
            var form_keyid = tokens.get("KeyID");
            // Delete the record that corresponds to the key ID using
            // the del method to send a DELETE request
            // to the storage/collections/data/{collection}/ endpoint
            service.del("storage/collections/data/dashboard_input_settings/" + encodeURIComponent(form_keyid));
            alert("Deleted...");
        });
    });

If the KVStore JS loaded log is not present in your browser's console, then the JS May have syntax error. If anything does not work you would need to provide additional details from console log.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

mwdbhyat
Builder

Thanks your code added another feature I wanted - however my original problem I realised I didn't define the variable for the rest handler itself - var service = mvc.createService({ owner: "nobody" });

So thats why it was doing nothing.. But thanks for the additional input!

harshpatel
Contributor

that's what I commented first 😄

niketn
Legend

Just noticed that as well 🙂 Up voted for hitting bull's eye!

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

harshpatel
Contributor

Thanks. Appreciate it 🙂

0 Karma

niketn
Legend

😄 cant believe I missed looking for that. Yes rest call need app and owner context. It runs with current app and current role by default (if not provided) . So it would fail if they do not match. Hence in your case owner nobody was required to be mentioned explicitely.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

harshpatel
Contributor

hi @mwdbhyat can you please look into browser console for any errors?
because I see that you have not created the service object before using it.

harishalipaka
Motivator

hi @mwdbhyat

try this code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Customer Info HTML</title>
    <link rel="shortcut icon" href="{{SPLUNKWEB_URL_PREFIX}}/static/img/favicon.ico" />
        <link rel="stylesheet" type="text/css" href="/en-US/static/@387cc49a8ed8/css/build/bootstrap.min.css" />
        <link rel="stylesheet" type="text/css" href="/en-US/static/@387cc49a8ed8/css/build/pages/dashboard-simple-bootstrap.min.css" />
</head>
<body class="simplexml preload locale-en">
<!-- 
BEGIN LAYOUT
This section contains the layout for the dashboard. Splunk uses proprietary
styles in <div> tags, similar to Bootstrap's grid system. 
-->
<a class="navSkip" href="#navSkip" tabindex="1">Screen reader users, click here to skip the navigation bar</a>
<div class="header splunk-header">
        <div id="placeholder-splunk-bar">
            <a href="{{SPLUNKWEB_URL_PREFIX}}/app/launcher/home" class="brand" title="splunk > listen to your data">splunk<strong>></strong></a>
        </div>
            <div id="placeholder-app-bar"></div>
</div>
<a id="navSkip"></a>

<div class="dashboard-body container-fluid main-section-body" data-role="main">
    <h3>Customer Info</h3>

    <form id="formCustomerInfo">
        <div class="fieldset">
            <div class="input input-text" id="input1">
                <label>CustID</label>
            </div>
            <div class="input input-text" id="input2">
                <label>CustName</label>
            </div>
            &lt;br/&gt;
            <div class="input input-text" id="input3">
                <label>CustStreet</label>
            </div>
            <div class="input input-text" id="input4">
                <label>CustCity</label>
            </div>
            <div class="input input-text" id="input5">
                <label>CustState</label>
            </div>
            <div class="input input-text" id="input6">
                <label>CustZip</label>
            </div>
            <div class="form-submit" id="search_btn">
                <button class="btn btn-primary submit">Submit</button>
            </div>
        </div>

        <div>
            <div class="input input-text" id="input7">
                <label>Enter a Key ID from the table below</label>
            </div>
            <div><button id="deleteRecord">Delete Record</button></div>
        </div>&lt;br/&gt;
    </form>

    <div id="row1" class="dashboard-row dashboard-row1">
        <div id="panel1" class="dashboard-cell" style="width: 100%;">                
            <div class="panel-element-row">
                <div id="element1" class="dashboard-element table" style="width: 100%">
                    <div class="panel-head">
                        <h3>KV Store collection</h3>
                    </div>
                    <div class="panel-body"></div>
                </div>
            </div>
        </div>
    </div>

</div>
<div class="footer"></div>

<!-- 
END LAYOUT
-->

<script src="{{SPLUNKWEB_URL_PREFIX}}/config?autoload=1"></script>
<script src="{{SPLUNKWEB_URL_PREFIX}}/static/js/i18n.js"></script>
<script src="{{SPLUNKWEB_URL_PREFIX}}/i18ncatalog?autoload=1"></script>
<script src="{{SPLUNKWEB_URL_PREFIX}}/static/js/build/simplexml.min/config.js"></script>
<script type="text/javascript">
// <![CDATA[
require.config({
    baseUrl: "{{SPLUNKWEB_URL_PREFIX}}/static/js",
    waitSeconds: 0 // Disable require.js load timeout
});

//
// LIBRARY REQUIREMENTS
//
// In the require function, we include the necessary libraries and modules for
// the HTML dashboard. Then, we pass variable names for these libraries and
// modules as function parameters, in order.
// 
// When you add libraries or modules, remember to retain this mapping order
// between the library or module and its function parameter. You can do this by
// adding to the end of these lists, as shown in the commented examples below.

require([
    "splunkjs/mvc",
    "splunkjs/mvc/utils",
    "splunkjs/mvc/tokenutils",
    "underscore",
    "jquery",
    "splunkjs/mvc/simplexml",
    "splunkjs/mvc/headerview",
    "splunkjs/mvc/footerview",
    "splunkjs/mvc/simplexml/dashboardview",
    "splunkjs/mvc/simplexml/dashboard/panelref",
    "splunkjs/mvc/simplexml/element/chart",
    "splunkjs/mvc/simplexml/element/event",
    "splunkjs/mvc/simplexml/element/html",
    "splunkjs/mvc/simplexml/element/list",
    "splunkjs/mvc/simplexml/element/map",
    "splunkjs/mvc/simplexml/element/single",
    "splunkjs/mvc/simplexml/element/table",
    "splunkjs/mvc/simpleform/formutils",
    "splunkjs/mvc/simplexml/eventhandler",
    "splunkjs/mvc/simplexml/searcheventhandler",
    "splunkjs/mvc/simpleform/input/dropdown",
    "splunkjs/mvc/simpleform/input/radiogroup",
    "splunkjs/mvc/simpleform/input/linklist",
    "splunkjs/mvc/simpleform/input/multiselect",
    "splunkjs/mvc/simpleform/input/checkboxgroup",
    "splunkjs/mvc/simpleform/input/text",
    "splunkjs/mvc/simpleform/input/timerange",
    "splunkjs/mvc/simpleform/input/submit",
    "splunkjs/mvc/searchmanager",
    "splunkjs/mvc/savedsearchmanager",
    "splunkjs/mvc/postprocessmanager",
    "splunkjs/mvc/simplexml/urltokenmodel"
    // Add comma-separated libraries and modules manually here, for example:
    // ..."splunkjs/mvc/simplexml/urltokenmodel",
    // "splunkjs/mvc/checkboxview"
    ],
    function(
        mvc,
        utils,
        TokenUtils,
        _,
        $,
        DashboardController,
        HeaderView,
        FooterView,
        Dashboard,
        PanelRef,
        ChartElement,
        EventElement,
        HtmlElement,
        ListElement,
        MapElement,
        SingleElement,
        TableElement,
        FormUtils,
        EventHandler,
        SearchEventHandler,
        DropdownInput,
        RadioGroupInput,
        LinkListInput,
        MultiSelectInput,
        CheckboxGroupInput,
        TextInput,
        TimeRangeInput,
        SubmitButton,
        SearchManager,
        SavedSearchManager,
        PostProcessManager,
        UrlTokenModel

        // Add comma-separated parameter names here, for example: 
        // ...UrlTokenModel, 
        // CheckboxView
        ) {

        var pageLoading = true;


        // 
        // TOKENS
        //

        // Create token namespaces
        var urlTokenModel = new UrlTokenModel();
        mvc.Components.registerInstance('url', urlTokenModel);
        var defaultTokenModel = mvc.Components.get('default', {create: true});
        var submittedTokenModel = mvc.Components.get('submitted', {create: true});

        urlTokenModel.on('url:navigate', function() {
            defaultTokenModel.set(urlTokenModel.toJSON());
            if (!_.isEmpty(urlTokenModel.toJSON()) && !_.all(urlTokenModel.toJSON(), _.isUndefined)) {
                submitTokens();
            } else {
                submittedTokenModel.clear();
            }
        });

        // Initialize tokens
        defaultTokenModel.set(urlTokenModel.toJSON());

        function submitTokens() {
            // Copy the contents of the defaultTokenModel to the submittedTokenModel and urlTokenModel
            FormUtils.submitForm({ replaceState: pageLoading });
        }

        function setToken(name, value) {
            defaultTokenModel.set(name, value);
            submittedTokenModel.set(name, value);
        }

        function unsetToken(name) {
            defaultTokenModel.unset(name);
            submittedTokenModel.unset(name);
        }



        //
        // SEARCH MANAGERS
        //

        var search1 = new SearchManager({
            "id": "search1",
            "cancelOnUnload": true,
            "latest_time": "$latest$",
            "status_buckets": 0,
            "earliest_time": "0",
            "search": " | inputlookup kvstore_lookup | eval  KeyID = _key | table KeyID, CustID, CustName, CustStreet, CustCity, CustState, CustZip",
            "app": utils.getCurrentApp(),
            "auto_cancel": 90,
            "preview": true,
            "runWhenTimeIsUndefined": false
        }, {tokens: true});


        //
        // SPLUNK HEADER AND FOOTER
        //

        new HeaderView({
            id: 'header',
            section: 'dashboards',
            el: $('.header'),
            acceleratedAppNav: true,
            useSessionStorageCache: true,
            splunkbar: true,
            appbar: true,
            litebar: false,
        }, {tokens: true}).render();

        new FooterView({
            id: 'footer',
            el: $('.footer')
        }, {tokens: true}).render();


        //
        // DASHBOARD EDITOR
        //

        new Dashboard({
            id: 'dashboard',
            el: $('.dashboard-body'),
            showTitle: true,
            editable: true
        }, {tokens: true}).render();


        //
        // VIEWS: VISUALIZATION ELEMENTS
        //

        var element1 = new TableElement({
            "id": "element1",
            "drilldown": "none",
            "rowNumbers": "undefined",
            "wrap": "undefined",
            "managerid": "search1",
            "el": $('#element1')
        }, {tokens: true, tokenNamespace: "submitted"}).render();


        //
        // VIEWS: FORM INPUTS
        //

        var input1 = new TextInput({
            "id": "input1",
            "value": "$form.CustID$",
            "el": $('#input1')
        }, {tokens: true}).render();

        input1.on("change", function(newValue) {
            FormUtils.handleValueChange(input1);
        });

        var input2 = new TextInput({
            "id": "input2",
            "value": "$form.CustName$",
            "el": $('#input2')
        }, {tokens: true}).render();

        input2.on("change", function(newValue) {
            FormUtils.handleValueChange(input2);
        });

        var input3 = new TextInput({
            "id": "input3",
            "value": "$form.CustStreet$",
            "el": $('#input3')
        }, {tokens: true}).render();

        input3.on("change", function(newValue) {
            FormUtils.handleValueChange(input3);
        });

        var input4 = new TextInput({
            "id": "input4",
            "value": "$form.CustCity$",
            "el": $('#input4')
        }, {tokens: true}).render();

        input4.on("change", function(newValue) {
            FormUtils.handleValueChange(input4);
        });

        var input5 = new TextInput({
            "id": "input5",
            "value": "$form.CustState$",
            "el": $('#input5')
        }, {tokens: true}).render();

        input5.on("change", function(newValue) {
            FormUtils.handleValueChange(input5);
        });

        var input6 = new TextInput({
            "id": "input6",
            "value": "$form.CustZip$",
            "el": $('#input6')
        }, {tokens: true}).render();

        input6.on("change", function(newValue) {
            FormUtils.handleValueChange(input6);
        });

        var input7 = new TextInput({
            "id": "input7",
            "value": "$form.KeyID$",
            "el": $('#input7')
        }, {tokens: true}).render();

        input7.on("change", function(newValue) {
            FormUtils.handleValueChange(input7);
        });

        // 
        // SERVICE OBJECT
        //

        // Create a service object using the Splunk SDK for JavaScript
        // to send REST requests
        var service = mvc.createService({ owner: "nobody" });


        // 
        // DELETE BUTTON
        //

        // Call this function when the Delete Record button is clicked
        $("#deleteRecord").click(function() {
            // Get the value of the key ID field
            var tokens = mvc.Components.get("default");
            var form_keyid = tokens.get("KeyID");

            // Delete the record that corresponds to the key ID using
            // the del method to send a DELETE request
            // to the storage/collections/data/{collection}/ endpoint
            service.del("storage/collections/data/mycollection/" + encodeURIComponent(form_keyid))
                .done(function() { 
                    // Run the search again to update the table
                    search1.startSearch(); 
                });
            return false;
        }); 


        // 
        // SUBMIT FORM DATA
        //

        var submit = new SubmitButton({
            id: 'submit',
            el: $('#search_btn')
        }, {tokens: true}).render();

        submit.on("submit", function() {
            submitTokens();

            // When the Submit button is clicked, get all the form fields by accessing token values
            var tokens = mvc.Components.get("default");
            var form_id = tokens.get("CustID");
            var form_name = tokens.get("CustName");
            var form_street = tokens.get("CustStreet");
            var form_city = tokens.get("CustCity");
            var form_state = tokens.get("CustState");
            var form_zip = tokens.get("CustZip");

            // Create a dictionary to store the field names and values
            var record = { 
                "CustID": form_id, 
                "CustName": form_name, 
                "CustStreet": form_street,
                "CustCity": form_city,
                "CustState": form_state,
                "CustZip": form_zip 
            }; 

            // Use the request method to send a REST POST request
            // to the storage/collections/data/{collection}/ endpoint
            service.request(
                "storage/collections/data/mycollection/",
                "POST",
                null,
                null,
                JSON.stringify(record),
                {"Content-Type": "application/json"},
                null)
                    .done(function() { 
                         // Run the search again to update the table
                        search1.startSearch();

                        // Clear the form fields 
                        $("#formCustomerInfo input[type=text]").val(""); 
                    });
        });

        // Initialize time tokens to default
        if (!defaultTokenModel.has('earliest') && !defaultTokenModel.has('latest')) {
            defaultTokenModel.set({ earliest: '0', latest: '' });
        }

        if (!_.isEmpty(urlTokenModel.toJSON())){
            submitTokens();
        }


        //
        // DASHBOARD READY
        //

        DashboardController.ready();
        pageLoading = false;

    }
);
// ]]>
</script>
</body>
</html>
Thanks
Harish
0 Karma
Get Updates on the Splunk Community!

Earn a $35 Gift Card for Answering our Splunk Admins & App Developer Survey

Survey for Splunk Admins and App Developers is open now! | Earn a $35 gift card!      Hello there,  Splunk ...

Continuing Innovation & New Integrations Unlock Full Stack Observability For Your ...

You’ve probably heard the latest about AppDynamics joining the Splunk Observability portfolio, deepening our ...

Monitoring Amazon Elastic Kubernetes Service (EKS)

As we’ve seen, integrating Kubernetes environments with Splunk Observability Cloud is a quick and easy way to ...