Skip to content
This repository has been archived by the owner on Sep 8, 2020. It is now read-only.

Problem with nested items being sorted #551

Open
ZtheLeader opened this issue Jun 7, 2018 · 3 comments
Open

Problem with nested items being sorted #551

ZtheLeader opened this issue Jun 7, 2018 · 3 comments

Comments

@ZtheLeader
Copy link

Hi I've implemented nested sortable items setup in surveys module in my project. i.e. I can sort Individual questions AND I can create an empty group, drop a single question into it and like this I fill up the group and I can sort the groups in hierarchy as well. Like this:

screen shot 2018-06-07 at 4 09 37 pm

Here's my code:

<!-- Group type questions: -->
                        <div class="row connector group-type-question-min-height-compulsory myHandle" ng-if="question.type == allQuestionTypes.group" ui-sortable="sortableOptionsGroup" ng-model="question.questions">
                        
                            <div class="col-md-6 col-sm-6 question-overview">
                                <div class="ellipsis">
                                    <i class="fa fa-bars"></i>
                        
                                    <input type="checkbox" ng-value="0" ng-model="question._selected" />
                                    <span ng-attr-title="{{question.name}}" ng-if="question.type == allQuestionTypes.group">
                                        <b>{{question.name}}</b>
                                    </span>
                        
                                </div>
                            </div>
                            <div class="col-md-6 col-sm-6 answer-overview pull-right word-wrap">
                                <span class="badge">{{showQuestionTypeText(question.type)}}</span>
                                <button type="button" ng-if="question.type != allQuestionTypes.group" class="button btn btn-success btn-sm" ng-click="$event.stopPropagation(); editSurveyQuestion(question, $index)">
                                    {{app.translateByLocale('label_edit')}}
                                </button>
                                <button type="button" ng-if="question.type == allQuestionTypes.group" class="button btn btn-success btn-sm" ng-click="$event.stopPropagation(); openModal(question, $index)">
                                    {{app.translateByLocale('label_edit')}}
                                </button>
                                <span class="delete-icon">
                                    <button class="btn btn-sm btn-danger" ng-click="$event.stopPropagation(); removeGroup(question)">
                                        <i class="fa fa-trash"></i>
                                    </button>
                                </span>
                            </div>
                            <div class="col-md-12 col-sm-12 question-overview group-type-question-bar" ng-if="question.questions.length == 0">
                                <div class="ellipsis text-center">
                                    <i class="fa fa-info-circle"></i>
                                    <span>
                                        {{app.translateByLocale('group_questions_drag_info')}}
                                    </span>
                                </div>
                                
                            </div>
                            <div ng-repeat="subQuestion in question.questions" class="group-type-question">
                                <div class="col-md-5 col-sm-5 question-overview" style="margin-left: 34px">
                                    <div class="ellipsis">
                                        <i class="fa fa-bars myHandle"></i>
                                        <!-- <input type="checkbox" ng-value="0" ng-model="subQuestion._selected" /> -->
                                        <span ng-attr-title="{{subQuestion.text}}">
                                            {{subQuestion.text}}
                                        </span>
                                    </div>
                                </div>
                                <div class="col-md-6 col-sm-6 answer-overview pull-right word-wrap">
                                <span class="badge">{{subQuestion.predefined_mcq_type.title}}</span>
                                    <span class="badge">{{showQuestionTypeText(subQuestion.type)}}</span>
                                    <button type="button" class="button btn btn-success btn-xs" ng-click="$event.stopPropagation(); editSurveyQuestion(subQuestion, $index)">
                                        {{app.translateByLocale('label_edit')}}
                                    </button>
                                    <span class="delete-icon">
                                        <button class="btn btn-xs btn-danger" ng-click="$event.stopPropagation(); removeSurveyGroupQuestion(subQuestion, question.questions)">
                                            <i class="fa fa-trash"></i>
                                        </button>
                                    </span>
                                </div>
                                </div>
                        </div>

Related Functions from Controller:

 * Defines the options for Group type questions to be used in both Survey creation and Edit
 * @param {object} scope 
 */
    function sortableOptionsGroup(scope) {

        let sortableGroup = {
            handle: '.myHandle',
            receive: function (event, ui) {
                sortingReceivedFunction(event, ui, scope);
            },
            remove: function (event, ui) {
                sortingRemovedFunction(event, ui, scope);
            },
            axis: 'y',
            'ui-floating': false,
            dropOnEmpty: true,
            cursor: 'move',
            tolerance: 'pointer',
            connectWith: '.connector'
        }
        return sortableGroup;
    }

    /**
     * invoked when an item is added to the main group
     * 
     * @param {obj} event 
     * @param {obj} ui 
     * @param {obj} scope 
     * 
     * @returns none
     */
    function sortingReceivedFunction(event, ui, scope) {       
        let obj = ui.item.sortable.model;
        let index = ui.item.sortable.index;
        let group_type = null;
        let invalidIncomingQuestion = false;
        
        //Group Questions Types Maintaining
        // when second and more questions are added:
        if (ui.item.sortable.droptargetModel.length >= 1){
            _.map(ui.item.sortable.droptargetModel, function (questionObject) {
                if (questionObject.type == allQuestionTypes.mcq && ui.item.sortable.model.type == allQuestionTypes.mcq && (questionObject.predefined_mcq_type.key != ui.item.sortable.model.predefined_mcq_type.key)) {
                    invalidIncomingQuestion = true;
                }
            });
            if(invalidIncomingQuestion){
                showErrorMessage(localeService.translateByLocale("group_question_error4"));
                cancelDraging(index, obj, scope, ui);
                return;
            }
            else if (ui.item.sortable.droptargetModel.length == maxQuestionLimitInGroup) {
                showErrorMessage(localeService.translateByLocale("group_question_error3"));
                cancelDraging(index, obj, scope, ui);
            }
            else if (incomingMcqQuestionValidation(ui.item.sortable.model)) {
                cancelDraging(index, obj, scope, ui);
            }
            else if (incomingCustomQuestionValidation(ui.item.sortable.model)){
                cancelDraging(index, obj, scope, ui);
            }
            else {
                let groupQuestionId = ui.item.sortable.model.id;
                scope.questions.data.forEach(function (item, i, val) {
                    if (scope.questions.data[i].id == groupQuestionId) {
                        scope.questions.data[i].isSelected = false;
                    }
                });
            }

        }
        // when first question is added:
        else if (incomingMcqQuestionValidation(ui.item.sortable.model)) {
            cancelDraging(index, obj, scope, ui);
        }
        else if (incomingCustomQuestionValidation(ui.item.sortable.model)){
            cancelDraging(index, obj, scope, ui);
        }
        else {
            let groupQuestionId = ui.item.sortable.model.id;
            scope.questions.data.forEach(function (item, i, val) {
                if (scope.questions.data[i].id == groupQuestionId) {
                    scope.questions.data[i].isSelected = false;
                }
            });
        }
    }
    /**
     * invoked when an item is removed from the main group 
     * 
     * @param {obj} event 
     * @param {obj} ui 
     * @param {obj} scope 
     * 
     * @returns none
     */
    function sortingRemovedFunction(event, ui, scope) {
        let groupQuestionId = ui.item.sortable.model.id;
        scope.questions.data.forEach(function (item, i, val) {
            if (scope.questions.data[i].id == groupQuestionId) {
                scope.questions.data[i].isSelected = true;
            }
        });
    }

Things are working pretty fine but there are few problems.

1- When there are two adjacent groups and I try to drag an individual question into upper group, it always gets added into the lower/second group.

See in the image: I added here is the text for question in group 1 but it added in group 2. Model of group 1 is in console
screen shot 2018-06-07 at 4 23 56 pm

2- I can't sort the questions into a group.

Can someone help me here on it. I've been trying quite hard on it.

@thgreasi
Copy link
Contributor

thgreasi commented Jun 7, 2018

Wow that's a lot of code...
My first question will be whether you checked the Tree with dynamic template example found in README.
Are you defining the ui-sortable on each sub-sortable tree?

@ZtheLeader
Copy link
Author

1- I checked that and that was too complex to understand. Also all of my module is working fine except these two bugs so don't wan't to replace or modify all the code base. What I think is I'm missing some little thing which is causing all this.

2- Yes. as group are added dynamically into the parent sortable array so I put a separate ui-sortable for sub-sortable trees as well. So there are 2 ui-sortable. One for parent array and one for sub-sortable array.

@thgreasi
Copy link
Contributor

What version are you using?
Can you track by id or something in your ng-repeats?
Can you share a bit more info about the top level question's code?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants